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