A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
qos-txop.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2006, 2009 INRIA
3 * Copyright (c) 2009 MIRKO BANCHI
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 * Mirko Banchi <mk.banchi@gmail.com>
20 * Stefano Avallone <stavalli@unina.it>
21 */
22
23#include "qos-txop.h"
24
26#include "ctrl-headers.h"
27#include "mac-tx-middle.h"
28#include "mgt-action-headers.h"
29#include "mpdu-aggregator.h"
30#include "msdu-aggregator.h"
32#include "wifi-mac-queue.h"
33#include "wifi-mac-trailer.h"
34#include "wifi-phy.h"
35#include "wifi-psdu.h"
36#include "wifi-tx-parameters.h"
37
38#include "ns3/ht-configuration.h"
39#include "ns3/ht-frame-exchange-manager.h"
40#include "ns3/log.h"
41#include "ns3/pointer.h"
42#include "ns3/random-variable-stream.h"
43#include "ns3/simulator.h"
44
45#undef NS_LOG_APPEND_CONTEXT
46#define NS_LOG_APPEND_CONTEXT WIFI_TXOP_NS_LOG_APPEND_CONTEXT
47
48namespace ns3
49{
50
52
54
55TypeId
57{
58 static TypeId tid =
59 TypeId("ns3::QosTxop")
61 .SetGroupName("Wifi")
62 .AddConstructor<QosTxop>()
63 .AddAttribute("UseExplicitBarAfterMissedBlockAck",
64 "Specify whether explicit BlockAckRequest should be sent upon missed "
65 "BlockAck Response.",
66 BooleanValue(true),
69 .AddAttribute("AddBaResponseTimeout",
70 "The timeout to wait for ADDBA response after the Ack to "
71 "ADDBA request is received.",
76 .AddAttribute(
77 "FailedAddBaTimeout",
78 "The timeout after a failed BA agreement. During this "
79 "timeout, the originator resumes sending packets using normal "
80 "MPDU. After that, BA agreement is reset and the originator "
81 "will retry BA negotiation.",
85 .AddAttribute("BlockAckManager",
86 "The BlockAckManager object.",
89 MakePointerChecker<BlockAckManager>())
90 .AddAttribute("NMaxInflights",
91 "The maximum number of links (in the range 1-15) on which an MPDU can be "
92 "simultaneously in-flight.",
95 MakeUintegerChecker<uint8_t>(1, 15))
96 .AddTraceSource("TxopTrace",
97 "Trace source for TXOP start and duration times",
99 "ns3::QosTxop::TxopTracedCallback");
100 return tid;
101}
102
104{
105 NS_LOG_FUNCTION(this);
106 m_baManager = CreateObject<BlockAckManager>();
107}
108
109void
111{
112 NS_LOG_FUNCTION(this << aci);
114 m_ac = aci;
115 m_baManager->SetQueue(m_queue);
116 m_baManager->SetBlockDestinationCallback(
117 Callback<void, Mac48Address, uint8_t>([this](Mac48Address recipient, uint8_t tid) {
119 m_ac,
121 recipient,
122 m_mac->GetLocalAddress(recipient),
123 {tid});
124 }));
125 m_baManager->SetUnblockDestinationCallback(
126 Callback<void, Mac48Address, uint8_t>([this](Mac48Address recipient, uint8_t tid) {
127 // save the status of AC queues before unblocking the transmissions to the recipient
128 std::map<uint8_t, bool> hasFramesToTransmit;
129 for (const auto& [id, link] : GetLinks())
130 {
131 hasFramesToTransmit[id] = HasFramesToTransmit(id);
132 }
133
135 m_ac,
137 recipient,
138 m_mac->GetLocalAddress(recipient),
139 {tid});
140
141 // start access (if needed) on all the links
142 for (const auto& [id, link] : GetLinks())
143 {
144 StartAccessAfterEvent(id, hasFramesToTransmit.at(id), CHECK_MEDIUM_BUSY);
145 }
146 }));
147 m_queue->TraceConnectWithoutContext(
148 "Expired",
150}
151
153{
154 NS_LOG_FUNCTION(this);
155}
156
157void
159{
160 NS_LOG_FUNCTION(this);
161 if (m_baManager)
162 {
163 m_baManager->Dispose();
164 }
165 m_baManager = nullptr;
167}
168
169std::unique_ptr<Txop::LinkEntity>
171{
172 return std::make_unique<QosLinkEntity>();
173}
174
176QosTxop::GetLink(uint8_t linkId) const
177{
178 return static_cast<QosLinkEntity&>(Txop::GetLink(linkId));
179}
180
181uint8_t
182QosTxop::GetQosQueueSize(uint8_t tid, Mac48Address receiver) const
183{
185 uint32_t bufferSize = m_queue->GetNBytes(queueId);
186 // A queue size value of 254 is used for all sizes greater than 64 768 octets.
187 uint8_t queueSize = static_cast<uint8_t>(std::ceil(std::min(bufferSize, 64769U) / 256.0));
188 NS_LOG_DEBUG("Buffer size=" << bufferSize << " Queue Size=" << +queueSize);
189 return queueSize;
190}
191
192void
194{
195 NS_LOG_FUNCTION(this << &callback);
197 m_baManager->SetDroppedOldMpduCallback(callback.Bind(WIFI_MAC_DROP_QOS_OLD_PACKET));
198}
199
200void
201QosTxop::SetMuCwMin(uint16_t cwMin, uint8_t linkId)
202{
203 NS_LOG_FUNCTION(this << cwMin << +linkId);
204 GetLink(linkId).muCwMin = cwMin;
205}
206
207void
208QosTxop::SetMuCwMax(uint16_t cwMax, uint8_t linkId)
209{
210 NS_LOG_FUNCTION(this << cwMax << +linkId);
211 GetLink(linkId).muCwMax = cwMax;
212}
213
214void
215QosTxop::SetMuAifsn(uint8_t aifsn, uint8_t linkId)
216{
217 NS_LOG_FUNCTION(this << +aifsn << +linkId);
218 GetLink(linkId).muAifsn = aifsn;
219}
220
221void
222QosTxop::SetMuEdcaTimer(Time timer, uint8_t linkId)
223{
224 NS_LOG_FUNCTION(this << timer << +linkId);
225 GetLink(linkId).muEdcaTimer = timer;
226}
227
228void
230{
231 NS_LOG_FUNCTION(this << +linkId);
232 auto& link = GetLink(linkId);
233 link.muEdcaTimerStartTime = Simulator::Now();
234 if (EdcaDisabled(linkId))
235 {
236 NS_LOG_DEBUG("Disable EDCA for " << link.muEdcaTimer.As(Time::MS));
237 m_mac->GetChannelAccessManager(linkId)->DisableEdcaFor(this, link.muEdcaTimer);
238 }
239}
240
241bool
242QosTxop::MuEdcaTimerRunning(uint8_t linkId) const
243{
244 auto& link = GetLink(linkId);
245 return (link.muEdcaTimerStartTime.IsStrictlyPositive() &&
246 link.muEdcaTimer.IsStrictlyPositive() &&
247 link.muEdcaTimerStartTime + link.muEdcaTimer > Simulator::Now());
248}
249
250bool
251QosTxop::EdcaDisabled(uint8_t linkId) const
252{
253 return (MuEdcaTimerRunning(linkId) && GetLink(linkId).muAifsn == 0);
254}
255
257QosTxop::GetMinCw(uint8_t linkId) const
258{
259 if (!MuEdcaTimerRunning(linkId))
260 {
261 return GetLink(linkId).cwMin;
262 }
263 NS_ASSERT(!EdcaDisabled(linkId));
264 return GetLink(linkId).muCwMin;
265}
266
268QosTxop::GetMaxCw(uint8_t linkId) const
269{
270 if (!MuEdcaTimerRunning(linkId))
271 {
272 return GetLink(linkId).cwMax;
273 }
274 NS_ASSERT(!EdcaDisabled(linkId));
275 return GetLink(linkId).muCwMax;
276}
277
278uint8_t
279QosTxop::GetAifsn(uint8_t linkId) const
280{
281 if (!MuEdcaTimerRunning(linkId))
282 {
283 return GetLink(linkId).aifsn;
284 }
285 return GetLink(linkId).muAifsn;
286}
287
290{
291 return m_baManager;
292}
293
294uint16_t
295QosTxop::GetBaBufferSize(Mac48Address address, uint8_t tid) const
296{
297 return m_baManager->GetRecipientBufferSize(address, tid);
298}
299
300uint16_t
302{
303 return m_baManager->GetOriginatorStartingSequence(address, tid);
304}
305
306std::pair<CtrlBAckRequestHeader, WifiMacHeader>
308{
309 NS_LOG_FUNCTION(this << recipient << +tid);
311
312 auto recipientMld = m_mac->GetMldAddress(recipient);
313
314 CtrlBAckRequestHeader reqHdr =
315 m_baManager->GetBlockAckReqHeader(recipientMld.value_or(recipient), tid);
316
317 WifiMacHeader hdr;
319 hdr.SetAddr1(recipient);
320 hdr.SetAddr2(m_mac->GetLocalAddress(recipient));
321 hdr.SetDsNotTo();
322 hdr.SetDsNotFrom();
323 hdr.SetNoRetry();
324 hdr.SetNoMoreFragments();
325
326 return {reqHdr, hdr};
327}
328
329bool
331{
333}
334
335bool
337{
338 // remove MSDUs with expired lifetime starting from the head of the queue
339 m_queue->WipeAllExpiredMpdus();
340 auto hasFramesToTransmit = static_cast<bool>(m_queue->PeekFirstAvailable(linkId));
341
342 // Print the number of packets that are actually in the queue (which might not be
343 // eligible for transmission for some reason, e.g., TID not mapped to the link, etc.)
344 NS_LOG_DEBUG(m_ac << " on link " << +linkId << (hasFramesToTransmit ? " has" : " has not")
345 << " frames to transmit with " << m_queue->GetNPackets()
346 << " packets in the queue");
347 return hasFramesToTransmit;
348}
349
350uint16_t
352{
353 return m_txMiddle->GetNextSequenceNumberFor(hdr);
354}
355
356uint16_t
358{
359 return m_txMiddle->PeekNextSequenceNumberFor(hdr);
360}
361
362bool
364{
365 NS_LOG_FUNCTION(this << *mpdu);
366
367 if (!mpdu->GetHeader().IsQosData())
368 {
369 return false;
370 }
371
372 Mac48Address recipient = mpdu->GetHeader().GetAddr1();
373 uint8_t tid = mpdu->GetHeader().GetQosTid();
374
375 if (!m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid))
376 {
377 return false;
378 }
379
380 return QosUtilsIsOldPacket(GetBaStartingSequence(recipient, tid),
381 mpdu->GetHeader().GetSequenceNumber());
382}
383
385QosTxop::PeekNextMpdu(uint8_t linkId, uint8_t tid, Mac48Address recipient, Ptr<const WifiMpdu> mpdu)
386{
387 NS_LOG_FUNCTION(this << +linkId << +tid << recipient << mpdu);
388
389 // lambda to peek the next frame
390 auto peek = [this, &linkId, &tid, &recipient, &mpdu]() -> Ptr<WifiMpdu> {
391 if (tid == 8 && recipient.IsBroadcast()) // undefined TID and recipient
392 {
393 return m_queue->PeekFirstAvailable(linkId, mpdu);
394 }
395 WifiContainerQueueId queueId(WIFI_QOSDATA_QUEUE, WIFI_UNICAST, recipient, tid);
396 if (auto mask = m_mac->GetMacQueueScheduler()->GetQueueLinkMask(m_ac, queueId, linkId);
397 mask && mask->none())
398 {
399 return m_queue->PeekByQueueId(queueId, mpdu);
400 }
401 return nullptr;
402 };
403
404 auto item = peek();
405 // remove old packets (must be retransmissions or in flight, otherwise they did
406 // not get a sequence number assigned)
407 while (item && !item->IsFragment())
408 {
409 if (item->GetHeader().IsCtl())
410 {
411 NS_LOG_DEBUG("Skipping control frame: " << *item);
412 mpdu = item;
413 item = peek();
414 continue;
415 }
416
417 if (item->HasSeqNoAssigned() && IsQosOldPacket(item))
418 {
419 NS_LOG_DEBUG("Removing an old packet from EDCA queue: " << *item);
421 {
423 }
424 mpdu = item;
425 item = peek();
426 m_queue->Remove(mpdu);
427 continue;
428 }
429
430 if (auto linkIds = item->GetInFlightLinkIds(); !linkIds.empty()) // MPDU is in-flight
431 {
432 // if the MPDU is not already in-flight on the link for which we are requesting an
433 // MPDU and the number of links on which the MPDU is in-flight is less than the
434 // maximum number, then we can transmit this MPDU
435 if (!linkIds.contains(linkId) && (linkIds.size() < m_nMaxInflights))
436 {
437 break;
438 }
439
440 // if no BA agreement, we cannot have multiple MPDUs in-flight
441 if (item->GetHeader().IsQosData() &&
442 !m_mac->GetBaAgreementEstablishedAsOriginator(item->GetHeader().GetAddr1(),
443 item->GetHeader().GetQosTid()))
444 {
445 NS_LOG_DEBUG("No BA agreement and an MPDU is already in-flight");
446 return nullptr;
447 }
448
449 NS_LOG_DEBUG("Skipping in flight MPDU: " << *item);
450 mpdu = item;
451 item = peek();
452 continue;
453 }
454
455 if (item->GetHeader().HasData() &&
456 !m_mac->CanForwardPacketsTo(item->GetHeader().GetAddr1()))
457 {
458 NS_LOG_DEBUG("Skipping frame that cannot be forwarded: " << *item);
459 mpdu = item;
460 item = peek();
461 continue;
462 }
463 break;
464 }
465
466 if (!item)
467 {
468 return nullptr;
469 }
470
471 WifiMacHeader& hdr = item->GetHeader();
472
473 // peek the next sequence number and check if it is within the transmit window
474 // in case of QoS data frame
475 uint16_t sequence = item->HasSeqNoAssigned() ? hdr.GetSequenceNumber()
476 : m_txMiddle->PeekNextSequenceNumberFor(&hdr);
477 if (hdr.IsQosData())
478 {
479 Mac48Address recipient = hdr.GetAddr1();
480 uint8_t tid = hdr.GetQosTid();
481
482 if (m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid) &&
483 !IsInWindow(sequence,
484 GetBaStartingSequence(recipient, tid),
485 GetBaBufferSize(recipient, tid)))
486 {
487 NS_LOG_DEBUG("Packet beyond the end of the current transmit window");
488 return nullptr;
489 }
490 }
491
492 // Assign a sequence number if this is not a fragment nor it already has one assigned
493 if (!item->IsFragment() && !item->HasSeqNoAssigned())
494 {
495 hdr.SetSequenceNumber(sequence);
496 }
497 NS_LOG_DEBUG("Packet peeked from EDCA queue: " << *item);
498 return item;
499}
500
502QosTxop::GetNextMpdu(uint8_t linkId,
503 Ptr<WifiMpdu> peekedItem,
504 WifiTxParameters& txParams,
505 Time availableTime,
506 bool initialFrame)
507{
508 NS_ASSERT(peekedItem);
509 NS_LOG_FUNCTION(this << +linkId << *peekedItem << &txParams << availableTime << initialFrame);
510
511 Mac48Address recipient = peekedItem->GetHeader().GetAddr1();
512
513 // The TXOP limit can be exceeded by the TXOP holder if it does not transmit more
514 // than one Data or Management frame in the TXOP and the frame is not in an A-MPDU
515 // consisting of more than one MPDU (Sec. 10.22.2.8 of 802.11-2016)
516 Time actualAvailableTime =
517 (initialFrame && txParams.GetSize(recipient) == 0 ? Time::Min() : availableTime);
518
519 auto qosFem = StaticCast<QosFrameExchangeManager>(m_mac->GetFrameExchangeManager(linkId));
520 if (!qosFem->TryAddMpdu(peekedItem, txParams, actualAvailableTime))
521 {
522 return nullptr;
523 }
524
525 NS_ASSERT(peekedItem->IsQueued());
526 Ptr<WifiMpdu> mpdu;
527
528 // If it is a non-broadcast QoS Data frame and it is not a retransmission nor a fragment,
529 // attempt A-MSDU aggregation
530 if (peekedItem->GetHeader().IsQosData())
531 {
532 uint8_t tid = peekedItem->GetHeader().GetQosTid();
533
534 // we should not be asked to dequeue an MPDU that is beyond the transmit window.
535 // Note that PeekNextMpdu() temporarily assigns the next available sequence number
536 // to the peeked frame
539 peekedItem->GetHeader().GetSequenceNumber(),
540 GetBaStartingSequence(peekedItem->GetOriginal()->GetHeader().GetAddr1(), tid),
541 GetBaBufferSize(peekedItem->GetOriginal()->GetHeader().GetAddr1(), tid)));
542
543 // try A-MSDU aggregation if the MPDU does not contain an A-MSDU and does not already
544 // have a sequence number assigned (may be a retransmission)
545 if (m_mac->GetHtConfiguration() && !recipient.IsBroadcast() &&
546 !peekedItem->GetHeader().IsQosAmsdu() && !peekedItem->HasSeqNoAssigned() &&
547 !peekedItem->IsFragment())
548 {
549 auto htFem = StaticCast<HtFrameExchangeManager>(qosFem);
550 mpdu = htFem->GetMsduAggregator()->GetNextAmsdu(peekedItem, txParams, availableTime);
551 }
552
553 if (mpdu)
554 {
555 NS_LOG_DEBUG("Prepared an MPDU containing an A-MSDU");
556 }
557 // else aggregation was not attempted or failed
558 }
559
560 if (!mpdu)
561 {
562 mpdu = peekedItem;
563 }
564
565 // Assign a sequence number if this is not a fragment nor a retransmission
567 NS_LOG_DEBUG("Got MPDU from EDCA queue: " << *mpdu);
568
569 return mpdu;
570}
571
572void
574{
575 NS_LOG_FUNCTION(this << *mpdu);
576
577 if (!mpdu->IsFragment() && !mpdu->HasSeqNoAssigned())
578 {
579 // in case of 11be MLDs, sequence numbers refer to the MLD address
580 auto origMpdu = m_queue->GetOriginal(mpdu);
581 uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor(&origMpdu->GetHeader());
582 mpdu->AssignSeqNo(sequence);
583 }
584}
585
586void
587QosTxop::NotifyChannelAccessed(uint8_t linkId, Time txopDuration)
588{
589 NS_LOG_FUNCTION(this << +linkId << txopDuration);
590
591 NS_ASSERT(txopDuration != Time::Min());
592 GetLink(linkId).startTxop = Simulator::Now();
593 GetLink(linkId).txopDuration = txopDuration;
595}
596
597std::optional<Time>
598QosTxop::GetTxopStartTime(uint8_t linkId) const
599{
600 auto& link = GetLink(linkId);
601 NS_LOG_FUNCTION(this << link.startTxop.has_value());
602 return link.startTxop;
603}
604
605void
607{
608 NS_LOG_FUNCTION(this << +linkId);
609 auto& link = GetLink(linkId);
610
611 if (link.startTxop)
612 {
613 NS_LOG_DEBUG("Terminating TXOP. Duration = " << Simulator::Now() - *link.startTxop);
614 m_txopTrace(*link.startTxop, Simulator::Now() - *link.startTxop, linkId);
615 }
616
617 // generate a new backoff value if either the TXOP duration is not null (i.e., some frames
618 // were transmitted) or no frame was transmitted but the queue actually contains frame to
619 // transmit and the user indicated that a backoff value should be generated in this situation.
620 // This behavior reflects the following specs text (Sec. 35.3.16.4 of 802.11be D4.0):
621 // An AP or non-AP STA affiliated with an MLD that has gained the right to initiate the
622 // transmission of a frame as described in 10.23.2.4 (Obtaining an EDCA TXOP) for an AC but
623 // does not transmit any frame corresponding to that AC for the reasons stated above may:
624 // - invoke a backoff for the EDCAF associated with that AC as allowed per h) of 10.23.2.2
625 // (EDCA backoff procedure).
626 auto hasTransmitted = link.startTxop.has_value() && Simulator::Now() > *link.startTxop;
627
628 m_queue->WipeAllExpiredMpdus();
629 if ((hasTransmitted) ||
631 {
632 GenerateBackoff(linkId);
633 if (!m_queue->IsEmpty())
634 {
636 }
637 }
638 link.startTxop.reset();
639 GetLink(linkId).access = NOT_REQUESTED;
640}
641
642Time
643QosTxop::GetRemainingTxop(uint8_t linkId) const
644{
645 auto& link = GetLink(linkId);
646 NS_ASSERT(link.startTxop.has_value());
647
648 Time remainingTxop = link.txopDuration;
649 remainingTxop -= (Simulator::Now() - *link.startTxop);
650 if (remainingTxop.IsStrictlyNegative())
651 {
652 remainingTxop = Seconds(0);
653 }
654 NS_LOG_FUNCTION(this << remainingTxop);
655 return remainingTxop;
656}
657
658void
660{
661 NS_LOG_FUNCTION(this << respHdr << recipient);
662 uint8_t tid = respHdr.GetTid();
663
664 if (respHdr.GetStatusCode().IsSuccess())
665 {
666 NS_LOG_DEBUG("block ack agreement established with " << recipient << " tid " << +tid);
667 // A (destination, TID) pair is "blocked" (i.e., no more packets are sent)
668 // when an Add BA Request is sent to the destination. However, when the
669 // Add BA Request timer expires, the (destination, TID) pair is "unblocked"
670 // and packets to the destination are sent again (under normal ack policy).
671 // Thus, there may be a packet needing to be retransmitted when the
672 // Add BA Response is received. In this case, the starting sequence number
673 // shall be set equal to the sequence number of such packet.
674 uint16_t startingSeq = m_txMiddle->GetNextSeqNumberByTidAndAddress(tid, recipient);
675 auto peekedItem = m_queue->PeekByTidAndAddress(tid, recipient);
676 if (peekedItem && peekedItem->GetHeader().IsRetry())
677 {
678 startingSeq = peekedItem->GetHeader().GetSequenceNumber();
679 }
680 m_baManager->UpdateOriginatorAgreement(respHdr, recipient, startingSeq);
681 }
682 else
683 {
684 NS_LOG_DEBUG("discard ADDBA response" << recipient);
685 m_baManager->NotifyOriginatorAgreementRejected(recipient, tid);
686 }
687}
688
689void
691{
692 NS_LOG_FUNCTION(this << delBaHdr << recipient);
693 NS_LOG_DEBUG("received DELBA frame from=" << recipient);
694 m_baManager->DestroyOriginatorAgreement(recipient, delBaHdr->GetTid());
695}
696
697void
699{
700 NS_LOG_FUNCTION(this << recipient << tid);
701 m_baManager->NotifyOriginatorAgreementNoReply(recipient, tid);
702}
703
704void
706{
707 NS_ASSERT(mpdu->GetHeader().IsQosData());
708 // If there is an established BA agreement, store the packet in the queue of outstanding packets
709 if (m_mac->GetBaAgreementEstablishedAsOriginator(mpdu->GetHeader().GetAddr1(),
710 mpdu->GetHeader().GetQosTid()))
711 {
712 NS_ASSERT(mpdu->IsQueued());
713 NS_ASSERT(m_queue->GetAc() == mpdu->GetQueueAc());
714 m_baManager->StorePacket(m_queue->GetOriginal(mpdu));
715 }
716}
717
718void
720{
721 NS_LOG_FUNCTION(this << +threshold);
722 m_blockAckThreshold = threshold;
723 m_baManager->SetBlockAckThreshold(threshold);
724}
725
726void
728{
729 NS_LOG_FUNCTION(this << timeout);
731}
732
733uint8_t
735{
736 NS_LOG_FUNCTION(this);
737 return m_blockAckThreshold;
738}
739
740uint16_t
742{
744}
745
746void
748{
749 NS_LOG_FUNCTION(this << recipient << +tid);
750 // If agreement is still pending, ADDBA response is not received
751 if (auto agreement = m_baManager->GetAgreementAsOriginator(recipient, tid);
752 agreement && agreement->get().IsPending())
753 {
754 NotifyOriginatorAgreementNoReply(recipient, tid);
756 }
757}
758
759void
760QosTxop::ResetBa(Mac48Address recipient, uint8_t tid)
761{
762 NS_LOG_FUNCTION(this << recipient << +tid);
763 // This function is scheduled when waiting for an ADDBA response. However,
764 // before this function is called, a DELBA request may arrive, which causes
765 // the agreement to be deleted. Hence, check if an agreement exists before
766 // notifying that the agreement has to be reset.
767 if (auto agreement = m_baManager->GetAgreementAsOriginator(recipient, tid);
768 agreement && !agreement->get().IsEstablished())
769 {
770 m_baManager->NotifyOriginatorAgreementReset(recipient, tid);
771 }
772}
773
774void
776{
777 NS_LOG_FUNCTION(this << addBaResponseTimeout);
778 m_addBaResponseTimeout = addBaResponseTimeout;
779}
780
781Time
783{
785}
786
787void
789{
790 NS_LOG_FUNCTION(this << failedAddBaTimeout);
791 m_failedAddBaTimeout = failedAddBaTimeout;
792}
793
794Time
796{
798}
799
800bool
802{
803 return true;
804}
805
808{
809 return m_ac;
810}
811
812} // namespace ns3
void NotifyDiscardedMpdu(Ptr< const WifiMpdu > mpdu)
Callback template class.
Definition: callback.h:438
bool IsNull() const
Check for null implementation.
Definition: callback.h:571
auto Bind(BoundArgs &&... bargs)
Bind a variable number of arguments.
Definition: callback.h:559
void DisableEdcaFor(Ptr< Txop > qosTxop, Time duration)
Headers for BlockAckRequest.
Definition: ctrl-headers.h:52
an EUI-48 address
Definition: mac48-address.h:46
bool IsBroadcast() const
Implement the header for management frames of type Add Block Ack response.
StatusCode GetStatusCode() const
Return the status code.
uint8_t GetTid() const
Return the Traffic ID (TID).
Implement the header for management frames of type Delete Block Ack.
uint8_t GetTid() const
Return the Traffic ID (TID).
AttributeValue implementation for Pointer.
Definition: pointer.h:48
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:74
std::unique_ptr< LinkEntity > CreateLinkEntity() const override
Create a LinkEntity object.
Definition: qos-txop.cc:170
~QosTxop() override
Definition: qos-txop.cc:152
uint8_t m_blockAckThreshold
the block ack threshold (use BA mechanism if number of packets in queue reaches this value.
Definition: qos-txop.h:464
Ptr< BlockAckManager > GetBaManager()
Get the Block Ack Manager associated with this QosTxop.
Definition: qos-txop.cc:289
Time m_failedAddBaTimeout
timeout after failed BA agreement
Definition: qos-txop.h:471
Ptr< WifiMpdu > PeekNextMpdu(uint8_t linkId, uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast(), Ptr< const WifiMpdu > mpdu=nullptr)
Peek the next frame to transmit on the given link to the given receiver and of the given TID from the...
Definition: qos-txop.cc:385
uint16_t PeekNextSequenceNumberFor(const WifiMacHeader *hdr)
Return the next sequence number for the Traffic ID and destination, but do not pick it (i....
Definition: qos-txop.cc:357
void SetMuCwMin(uint16_t cwMin, uint8_t linkId)
Set the minimum contention window size to use while the MU EDCA Timer is running for the given link.
Definition: qos-txop.cc:201
bool UseExplicitBarAfterMissedBlockAck() const
Return true if an explicit BlockAckRequest is sent after a missed BlockAck.
Definition: qos-txop.cc:330
bool EdcaDisabled(uint8_t linkId) const
Return true if the EDCA is disabled (the MU EDCA Timer is running and the MU AIFSN is zero) for the g...
Definition: qos-txop.cc:251
Time GetAddBaResponseTimeout() const
Get the timeout for ADDBA response.
Definition: qos-txop.cc:782
AcIndex GetAccessCategory() const
Get the access category of this object.
Definition: qos-txop.cc:807
void AddBaResponseTimeout(Mac48Address recipient, uint8_t tid)
Callback when ADDBA response is not received after timeout.
Definition: qos-txop.cc:747
uint16_t GetBaBufferSize(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:295
void DoDispose() override
Destructor implementation.
Definition: qos-txop.cc:158
void SetMuCwMax(uint16_t cwMax, uint8_t linkId)
Set the maximum contention window size to use while the MU EDCA Timer is running for the given link.
Definition: qos-txop.cc:208
bool MuEdcaTimerRunning(uint8_t linkId) const
Return true if the MU EDCA Timer is running for the given link, false otherwise.
Definition: qos-txop.cc:242
void StartMuEdcaTimerNow(uint8_t linkId)
Start the MU EDCA Timer for the given link.
Definition: qos-txop.cc:229
uint8_t GetBlockAckThreshold() const
Return the current threshold for block ack mechanism.
Definition: qos-txop.cc:734
void NotifyChannelReleased(uint8_t linkId) override
Called by the FrameExchangeManager to notify the completion of the transmissions.
Definition: qos-txop.cc:606
uint16_t GetNextSequenceNumberFor(const WifiMacHeader *hdr)
Return the next sequence number for the given header.
Definition: qos-txop.cc:351
uint16_t GetBlockAckInactivityTimeout() const
Get the BlockAck inactivity timeout.
Definition: qos-txop.cc:741
TxopTracedCallback m_txopTrace
TXOP trace callback.
Definition: qos-txop.h:482
virtual Time GetRemainingTxop(uint8_t linkId) const
Return the remaining duration in the current TXOP on the given link.
Definition: qos-txop.cc:643
AcIndex m_ac
the access category
Definition: qos-txop.h:462
void SetDroppedMpduCallback(DroppedMpdu callback) override
Definition: qos-txop.cc:193
bool m_useExplicitBarAfterMissedBlockAck
flag whether explicit BlockAckRequest should be sent upon missed BlockAck Response
Definition: qos-txop.h:472
void SetMuAifsn(uint8_t aifsn, uint8_t linkId)
Set the number of slots that make up an AIFS while the MU EDCA Timer is running for the given link.
Definition: qos-txop.cc:215
void NotifyOriginatorAgreementNoReply(const Mac48Address &recipient, uint8_t tid)
Take action upon notification of ADDBA_REQUEST frame being discarded (likely due to exceeded max retr...
Definition: qos-txop.cc:698
virtual std::optional< Time > GetTxopStartTime(uint8_t linkId) const
Definition: qos-txop.cc:598
uint8_t GetQosQueueSize(uint8_t tid, Mac48Address receiver) const
Get the value for the Queue Size subfield of the QoS Control field of a QoS data frame of the given T...
Definition: qos-txop.cc:182
void ResetBa(Mac48Address recipient, uint8_t tid)
Reset BA agreement after BA negotiation failed.
Definition: qos-txop.cc:760
Time GetFailedAddBaTimeout() const
Get the timeout for failed BA agreement.
Definition: qos-txop.cc:795
void GotAddBaResponse(const MgtAddBaResponseHeader &respHdr, Mac48Address recipient)
Event handler when an ADDBA response is received.
Definition: qos-txop.cc:659
static TypeId GetTypeId()
Get the type ID.
Definition: qos-txop.cc:56
void AssignSequenceNumber(Ptr< WifiMpdu > mpdu) const
Assign a sequence number to the given MPDU, if it is not a fragment and it is not a retransmitted fra...
Definition: qos-txop.cc:573
void SetFailedAddBaTimeout(Time failedAddBaTimeout)
Set the timeout for failed BA agreement.
Definition: qos-txop.cc:788
uint16_t m_blockAckInactivityTimeout
the BlockAck inactivity timeout value (in TUs, i.e.
Definition: qos-txop.h:468
QosLinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: qos-txop.cc:176
void CreateQueue(AcIndex aci) override
Create a wifi MAC queue containing packets of the given AC.
Definition: qos-txop.cc:110
Ptr< WifiMpdu > GetNextMpdu(uint8_t linkId, Ptr< WifiMpdu > peekedItem, WifiTxParameters &txParams, Time availableTime, bool initialFrame)
Prepare the frame to transmit on the given link starting from the MPDU that has been previously peeke...
Definition: qos-txop.cc:502
void SetBlockAckThreshold(uint8_t threshold)
Set threshold for block ack mechanism.
Definition: qos-txop.cc:719
bool IsQosOldPacket(Ptr< const WifiMpdu > mpdu)
Check if the given MPDU is to be considered old according to the current starting sequence number of ...
Definition: qos-txop.cc:363
void GotDelBaFrame(const MgtDelBaHeader *delBaHdr, Mac48Address recipient)
Event handler when a DELBA frame is received.
Definition: qos-txop.cc:690
void SetBlockAckInactivityTimeout(uint16_t timeout)
Set the BlockAck inactivity timeout.
Definition: qos-txop.cc:727
uint8_t m_nMaxInflights
the maximum number of links on which an MPDU can be in-flight at the same time
Definition: qos-txop.h:474
void CompleteMpduTx(Ptr< WifiMpdu > mpdu)
Stores an MPDU (part of an A-MPDU) in block ack agreement (i.e.
Definition: qos-txop.cc:705
void SetAddBaResponseTimeout(Time addBaResponseTimeout)
Set the timeout to wait for ADDBA response.
Definition: qos-txop.cc:775
std::pair< CtrlBAckRequestHeader, WifiMacHeader > PrepareBlockAckRequest(Mac48Address recipient, uint8_t tid) const
Definition: qos-txop.cc:307
bool HasFramesToTransmit(uint8_t linkId) override
Check if the Txop has frames to transmit over the given link.
Definition: qos-txop.cc:336
uint16_t GetBaStartingSequence(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:301
bool IsQosTxop() const override
Check for QoS TXOP.
Definition: qos-txop.cc:801
Time m_addBaResponseTimeout
timeout for ADDBA response
Definition: qos-txop.h:470
void NotifyChannelAccessed(uint8_t linkId, Time txopDuration) override
Called by the FrameExchangeManager to notify that channel access has been granted on the given link f...
Definition: qos-txop.cc:587
void SetMuEdcaTimer(Time timer, uint8_t linkId)
Set the MU EDCA Timer for the given link.
Definition: qos-txop.cc:222
Ptr< BlockAckManager > m_baManager
the block ack manager
Definition: qos-txop.h:463
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
bool IsSuccess() const
Return whether the status code is success.
Definition: status-code.cc:42
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:287
@ MS
millisecond
Definition: nstime.h:117
bool IsStrictlyNegative() const
Exactly equivalent to t < 0.
Definition: nstime.h:342
Handle packet fragmentation and retransmissions for data and management frames.
Definition: txop.h:82
Ptr< WifiMac > m_mac
the wifi MAC
Definition: txop.h:588
Ptr< WifiMacQueue > m_queue
the wifi MAC queue
Definition: txop.h:586
void StartAccessAfterEvent(uint8_t linkId, bool hadFramesToTransmit, bool checkMediumBusy)
Request channel access on the given link after the occurrence of an event that possibly requires to g...
Definition: txop.cc:703
void DoDispose() override
Destructor implementation.
Definition: txop.cc:189
uint32_t GetMinCw() const
Return the minimum contention window size.
Definition: txop.cc:518
@ NOT_REQUESTED
Definition: txop.h:103
virtual void CreateQueue(AcIndex aci)
Create a wifi MAC queue containing packets of the given AC.
Definition: txop.cc:200
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: txop.cc:214
DroppedMpdu m_droppedMpduCallback
the dropped MPDU callback
Definition: txop.h:585
const std::map< uint8_t, std::unique_ptr< LinkEntity > > & GetLinks() const
Definition: txop.cc:223
virtual void SetDroppedMpduCallback(DroppedMpdu callback)
Definition: txop.cc:264
virtual void GenerateBackoff(uint8_t linkId)
Generate a new backoff for the given link now.
Definition: txop.cc:789
Ptr< MacTxMiddle > m_txMiddle
the MacTxMiddle
Definition: txop.h:587
static constexpr bool CHECK_MEDIUM_BUSY
generation of backoff (also) depends on the busy/idle state of the medium
Definition: txop.h:426
virtual void NotifyChannelAccessed(uint8_t linkId, Time txopDuration=Seconds(0))
Called by the FrameExchangeManager to notify that channel access has been granted on the given link f...
Definition: txop.cc:760
void RequestAccess(uint8_t linkId)
Request access to the ChannelAccessManager associated with the given link.
Definition: txop.cc:779
uint8_t GetAifsn() const
Return the number of slots that make up an AIFS.
Definition: txop.cc:566
uint32_t GetMaxCw() const
Return the maximum contention window size.
Definition: txop.cc:542
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Hold an unsigned integer type.
Definition: uinteger.h:45
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
uint16_t GetSequenceNumber() const
Return the sequence number of the header.
void SetNoMoreFragments()
Un-set the More Fragment bit in the Frame Control Field.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
bool IsQosData() const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
void SetNoRetry()
Un-set the Retry bit in the Frame Control field.
Ptr< FrameExchangeManager > GetFrameExchangeManager(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get the Frame Exchange Manager associated with the given link.
Definition: wifi-mac.cc:981
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
Definition: wifi-mac.cc:1774
Ptr< WifiMacQueueScheduler > GetMacQueueScheduler() const
Get the wifi MAC queue scheduler.
Definition: wifi-mac.cc:670
Ptr< HtConfiguration > GetHtConfiguration() const
Definition: wifi-mac.cc:1879
Mac48Address GetLocalAddress(const Mac48Address &remoteAddr) const
Get the local MAC address used to communicate with a remote STA.
Definition: wifi-mac.cc:1787
OriginatorAgreementOptConstRef GetBaAgreementEstablishedAsOriginator(Mac48Address recipient, uint8_t tid) const
Definition: wifi-mac.cc:1821
virtual bool CanForwardPacketsTo(Mac48Address to) const =0
Return true if packets can be forwarded to the given destination, false otherwise.
Ptr< ChannelAccessManager > GetChannelAccessManager(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get the Channel Access Manager associated with the given link.
Definition: wifi-mac.cc:1009
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
uint32_t GetSize(Mac48Address receiver) const
Get the size in bytes of the (A-)MPDU addressed to the given receiver.
#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
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:259
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1331
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:134
bool QosUtilsIsOldPacket(uint16_t startingSeq, uint16_t seqNumber)
This function checks if packet with sequence number seqNumber is an "old" packet.
Definition: qos-utils.cc:182
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:73
@ WIFI_MAC_DROP_QOS_OLD_PACKET
Definition: wifi-mac.h:84
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1407
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:700
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
std::tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
@ WIFI_MAC_CTL_BACKREQ
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:81
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1427
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:121
ns3::Time timeout
std::ofstream queueSize