A Discrete-Event Network Simulator
API
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 
25 #include "channel-access-manager.h"
26 #include "ctrl-headers.h"
27 #include "mac-tx-middle.h"
28 #include "mgt-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-frame-exchange-manager.h"
39 #include "ns3/log.h"
40 #include "ns3/pointer.h"
41 #include "ns3/random-variable-stream.h"
42 #include "ns3/simulator.h"
43 
44 #undef NS_LOG_APPEND_CONTEXT
45 #define NS_LOG_APPEND_CONTEXT \
46  if (m_mac) \
47  { \
48  std::clog << "[mac=" << m_mac->GetAddress() << "] "; \
49  }
50 
51 namespace ns3
52 {
53 
54 NS_LOG_COMPONENT_DEFINE("QosTxop");
55 
57 
58 TypeId
60 {
61  static TypeId tid =
62  TypeId("ns3::QosTxop")
64  .SetGroupName("Wifi")
65  .AddConstructor<QosTxop>()
66  .AddAttribute("UseExplicitBarAfterMissedBlockAck",
67  "Specify whether explicit BlockAckRequest should be sent upon missed "
68  "BlockAck Response.",
69  BooleanValue(true),
72  .AddAttribute("AddBaResponseTimeout",
73  "The timeout to wait for ADDBA response after the Ack to "
74  "ADDBA request is received.",
79  .AddAttribute(
80  "FailedAddBaTimeout",
81  "The timeout after a failed BA agreement. During this "
82  "timeout, the originator resumes sending packets using normal "
83  "MPDU. After that, BA agreement is reset and the originator "
84  "will retry BA negotiation.",
85  TimeValue(MilliSeconds(200)),
88  .AddAttribute("BlockAckManager",
89  "The BlockAckManager object.",
90  PointerValue(),
92  MakePointerChecker<BlockAckManager>())
93  .AddAttribute("NMaxInflights",
94  "The maximum number of links (in the range 1-15) on which an MPDU can be "
95  "simultaneously in-flight.",
96  UintegerValue(1),
98  MakeUintegerChecker<uint8_t>(1, 15))
99  .AddTraceSource("TxopTrace",
100  "Trace source for TXOP start and duration times",
102  "ns3::QosTxop::TxopTracedCallback");
103  return tid;
104 }
105 
108  m_ac(ac)
109 {
110  NS_LOG_FUNCTION(this);
111  m_qosBlockedDestinations = Create<QosBlockedDestinations>();
112  m_baManager = CreateObject<BlockAckManager>();
113  m_baManager->SetQueue(m_queue);
114  m_baManager->SetBlockDestinationCallback(
116  m_baManager->SetUnblockDestinationCallback(
118  m_queue->TraceConnectWithoutContext(
119  "Expired",
121 }
122 
124 {
125  NS_LOG_FUNCTION(this);
126 }
127 
128 void
130 {
131  NS_LOG_FUNCTION(this);
132  if (m_baManager)
133  {
134  m_baManager->Dispose();
135  }
136  m_baManager = nullptr;
137  m_qosBlockedDestinations = nullptr;
138  Txop::DoDispose();
139 }
140 
141 std::unique_ptr<Txop::LinkEntity>
143 {
144  return std::make_unique<QosLinkEntity>();
145 }
146 
148 QosTxop::GetLink(uint8_t linkId) const
149 {
150  return static_cast<QosLinkEntity&>(Txop::GetLink(linkId));
151 }
152 
153 uint8_t
154 QosTxop::GetQosQueueSize(uint8_t tid, Mac48Address receiver) const
155 {
156  WifiContainerQueueId queueId{WIFI_QOSDATA_UNICAST_QUEUE, receiver, tid};
157  uint32_t bufferSize = m_queue->GetNBytes(queueId);
158  // A queue size value of 254 is used for all sizes greater than 64 768 octets.
159  uint8_t queueSize = static_cast<uint8_t>(std::ceil(std::min(bufferSize, 64769U) / 256.0));
160  NS_LOG_DEBUG("Buffer size=" << bufferSize << " Queue Size=" << +queueSize);
161  return queueSize;
162 }
163 
164 void
166 {
167  NS_LOG_FUNCTION(this << &callback);
169  m_baManager->SetDroppedOldMpduCallback(callback.Bind(WIFI_MAC_DROP_QOS_OLD_PACKET));
170 }
171 
172 void
173 QosTxop::SetMuCwMin(uint16_t cwMin, uint8_t linkId)
174 {
175  NS_LOG_FUNCTION(this << cwMin << +linkId);
176  GetLink(linkId).muCwMin = cwMin;
177 }
178 
179 void
180 QosTxop::SetMuCwMax(uint16_t cwMax, uint8_t linkId)
181 {
182  NS_LOG_FUNCTION(this << cwMax << +linkId);
183  GetLink(linkId).muCwMax = cwMax;
184 }
185 
186 void
187 QosTxop::SetMuAifsn(uint8_t aifsn, uint8_t linkId)
188 {
189  NS_LOG_FUNCTION(this << +aifsn << +linkId);
190  GetLink(linkId).muAifsn = aifsn;
191 }
192 
193 void
194 QosTxop::SetMuEdcaTimer(Time timer, uint8_t linkId)
195 {
196  NS_LOG_FUNCTION(this << timer << +linkId);
197  GetLink(linkId).muEdcaTimer = timer;
198 }
199 
200 void
202 {
203  NS_LOG_FUNCTION(this << +linkId);
204  auto& link = GetLink(linkId);
205  link.muEdcaTimerStartTime = Simulator::Now();
206  if (EdcaDisabled(linkId))
207  {
208  NS_LOG_DEBUG("Disable EDCA for " << link.muEdcaTimer.As(Time::MS));
209  m_mac->GetChannelAccessManager(linkId)->DisableEdcaFor(this, link.muEdcaTimer);
210  }
211 }
212 
213 bool
214 QosTxop::MuEdcaTimerRunning(uint8_t linkId) const
215 {
216  auto& link = GetLink(linkId);
217  return (link.muEdcaTimerStartTime.IsStrictlyPositive() &&
218  link.muEdcaTimer.IsStrictlyPositive() &&
219  link.muEdcaTimerStartTime + link.muEdcaTimer > Simulator::Now());
220 }
221 
222 bool
223 QosTxop::EdcaDisabled(uint8_t linkId) const
224 {
225  return (MuEdcaTimerRunning(linkId) && GetLink(linkId).muAifsn == 0);
226 }
227 
228 uint32_t
229 QosTxop::GetMinCw(uint8_t linkId) const
230 {
231  if (!MuEdcaTimerRunning(linkId))
232  {
233  return GetLink(linkId).cwMin;
234  }
235  NS_ASSERT(!EdcaDisabled(linkId));
236  return GetLink(linkId).muCwMin;
237 }
238 
239 uint32_t
240 QosTxop::GetMaxCw(uint8_t linkId) const
241 {
242  if (!MuEdcaTimerRunning(linkId))
243  {
244  return GetLink(linkId).cwMax;
245  }
246  NS_ASSERT(!EdcaDisabled(linkId));
247  return GetLink(linkId).muCwMax;
248 }
249 
250 uint8_t
251 QosTxop::GetAifsn(uint8_t linkId) const
252 {
253  if (!MuEdcaTimerRunning(linkId))
254  {
255  return GetLink(linkId).aifsn;
256  }
257  return GetLink(linkId).muAifsn;
258 }
259 
262 {
263  return m_baManager;
264 }
265 
266 uint16_t
268 {
269  return m_baManager->GetRecipientBufferSize(address, tid);
270 }
271 
272 uint16_t
274 {
275  return m_baManager->GetOriginatorStartingSequence(address, tid);
276 }
277 
279 QosTxop::PrepareBlockAckRequest(Mac48Address recipient, uint8_t tid) const
280 {
281  NS_LOG_FUNCTION(this << recipient << +tid);
283 
284  auto recipientMld = m_mac->GetMldAddress(recipient);
285 
286  CtrlBAckRequestHeader reqHdr =
287  m_baManager->GetBlockAckReqHeader(recipientMld.value_or(recipient), tid);
288  Ptr<Packet> bar = Create<Packet>();
289  bar->AddHeader(reqHdr);
290 
291  WifiMacHeader hdr;
293  hdr.SetAddr1(recipient);
294  hdr.SetAddr2(m_mac->GetLocalAddress(recipient));
295  hdr.SetDsNotTo();
296  hdr.SetDsNotFrom();
297  hdr.SetNoRetry();
298  hdr.SetNoMoreFragments();
299 
300  return Create<WifiMpdu>(bar, hdr);
301 }
302 
303 bool
305 {
307 }
308 
309 bool
311 {
312  // remove MSDUs with expired lifetime starting from the head of the queue
313  m_queue->WipeAllExpiredMpdus();
314  bool queueIsNotEmpty = (bool)(m_queue->PeekFirstAvailable(linkId, m_qosBlockedDestinations));
315 
316  NS_LOG_FUNCTION(this << queueIsNotEmpty);
317  return queueIsNotEmpty;
318 }
319 
320 uint16_t
322 {
323  return m_txMiddle->GetNextSequenceNumberFor(hdr);
324 }
325 
326 uint16_t
328 {
329  return m_txMiddle->PeekNextSequenceNumberFor(hdr);
330 }
331 
332 bool
334 {
335  NS_LOG_FUNCTION(this << *mpdu);
336 
337  if (!mpdu->GetHeader().IsQosData())
338  {
339  return false;
340  }
341 
342  Mac48Address recipient = mpdu->GetHeader().GetAddr1();
343  uint8_t tid = mpdu->GetHeader().GetQosTid();
344 
345  if (!m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid))
346  {
347  return false;
348  }
349 
350  if (QosUtilsIsOldPacket(GetBaStartingSequence(recipient, tid),
351  mpdu->GetHeader().GetSequenceNumber()))
352  {
353  return true;
354  }
355  return false;
356 }
357 
359 QosTxop::PeekNextMpdu(uint8_t linkId, uint8_t tid, Mac48Address recipient, Ptr<const WifiMpdu> mpdu)
360 {
361  NS_LOG_FUNCTION(this << +linkId << +tid << recipient << mpdu);
362 
363  // lambda to peek the next frame
364  auto peek = [this, &linkId, &tid, &recipient, &mpdu]() -> Ptr<WifiMpdu> {
365  if (tid == 8 && recipient.IsBroadcast()) // undefined TID and recipient
366  {
367  return m_queue->PeekFirstAvailable(linkId, m_qosBlockedDestinations, mpdu);
368  }
369  if (m_qosBlockedDestinations->IsBlocked(recipient, tid))
370  {
371  return nullptr;
372  }
373  return m_queue->PeekByTidAndAddress(tid, recipient, mpdu);
374  };
375 
376  auto item = peek();
377  // remove old packets (must be retransmissions or in flight, otherwise they did
378  // not get a sequence number assigned)
379  while (item && !item->IsFragment())
380  {
381  if (item->GetHeader().IsCtl())
382  {
383  NS_LOG_DEBUG("Skipping control frame: " << *item);
384  mpdu = item;
385  item = peek();
386  continue;
387  }
388 
389  if (item->HasSeqNoAssigned() && IsQosOldPacket(item))
390  {
391  NS_LOG_DEBUG("Removing an old packet from EDCA queue: " << *item);
393  {
395  }
396  mpdu = item;
397  item = peek();
398  m_queue->Remove(mpdu);
399  continue;
400  }
401 
402  if (auto linkIds = item->GetInFlightLinkIds(); !linkIds.empty()) // MPDU is in-flight
403  {
404  // if the MPDU is not already in-flight on the link for which we are requesting an
405  // MPDU and the number of links on which the MPDU is in-flight is less than the
406  // maximum number, then we can transmit this MPDU
407  if (linkIds.count(linkId) == 0 && linkIds.size() < m_nMaxInflights)
408  {
409  break;
410  }
411 
412  // if no BA agreement, we cannot have multiple MPDUs in-flight
413  if (item->GetHeader().IsQosData() &&
414  !m_mac->GetBaAgreementEstablishedAsOriginator(item->GetHeader().GetAddr1(),
415  item->GetHeader().GetQosTid()))
416  {
417  NS_LOG_DEBUG("No BA agreement and an MPDU is already in-flight");
418  return nullptr;
419  }
420 
421  NS_LOG_DEBUG("Skipping in flight MPDU: " << *item);
422  mpdu = item;
423  item = peek();
424  continue;
425  }
426 
427  if (item->GetHeader().HasData() &&
428  !m_mac->CanForwardPacketsTo(item->GetHeader().GetAddr1()))
429  {
430  NS_LOG_DEBUG("Skipping frame that cannot be forwarded: " << *item);
431  mpdu = item;
432  item = peek();
433  continue;
434  }
435  break;
436  }
437 
438  if (!item)
439  {
440  return nullptr;
441  }
442 
443  WifiMacHeader& hdr = item->GetHeader();
444 
445  // peek the next sequence number and check if it is within the transmit window
446  // in case of QoS data frame
447  uint16_t sequence = item->HasSeqNoAssigned() ? hdr.GetSequenceNumber()
448  : m_txMiddle->PeekNextSequenceNumberFor(&hdr);
449  if (hdr.IsQosData())
450  {
451  Mac48Address recipient = hdr.GetAddr1();
452  uint8_t tid = hdr.GetQosTid();
453 
454  if (m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid) &&
455  !IsInWindow(sequence,
456  GetBaStartingSequence(recipient, tid),
457  GetBaBufferSize(recipient, tid)))
458  {
459  NS_LOG_DEBUG("Packet beyond the end of the current transmit window");
460  return nullptr;
461  }
462  }
463 
464  // Assign a sequence number if this is not a fragment nor it already has one assigned
465  if (!item->IsFragment() && !item->HasSeqNoAssigned())
466  {
467  hdr.SetSequenceNumber(sequence);
468  }
469  NS_LOG_DEBUG("Packet peeked from EDCA queue: " << *item);
470  return item;
471 }
472 
474 QosTxop::GetNextMpdu(uint8_t linkId,
475  Ptr<WifiMpdu> peekedItem,
476  WifiTxParameters& txParams,
477  Time availableTime,
478  bool initialFrame)
479 {
480  NS_ASSERT(peekedItem);
481  NS_LOG_FUNCTION(this << +linkId << *peekedItem << &txParams << availableTime << initialFrame);
482 
483  Mac48Address recipient = peekedItem->GetHeader().GetAddr1();
484 
485  // The TXOP limit can be exceeded by the TXOP holder if it does not transmit more
486  // than one Data or Management frame in the TXOP and the frame is not in an A-MPDU
487  // consisting of more than one MPDU (Sec. 10.22.2.8 of 802.11-2016)
488  Time actualAvailableTime =
489  (initialFrame && txParams.GetSize(recipient) == 0 ? Time::Min() : availableTime);
490 
491  auto qosFem = StaticCast<QosFrameExchangeManager>(m_mac->GetFrameExchangeManager(linkId));
492  if (!qosFem->TryAddMpdu(peekedItem, txParams, actualAvailableTime))
493  {
494  return nullptr;
495  }
496 
497  NS_ASSERT(peekedItem->IsQueued());
498  Ptr<WifiMpdu> mpdu;
499 
500  // If it is a non-broadcast QoS Data frame and it is not a retransmission nor a fragment,
501  // attempt A-MSDU aggregation
502  if (peekedItem->GetHeader().IsQosData())
503  {
504  uint8_t tid = peekedItem->GetHeader().GetQosTid();
505 
506  // we should not be asked to dequeue an MPDU that is beyond the transmit window.
507  // Note that PeekNextMpdu() temporarily assigns the next available sequence number
508  // to the peeked frame
510  IsInWindow(
511  peekedItem->GetHeader().GetSequenceNumber(),
512  GetBaStartingSequence(peekedItem->GetOriginal()->GetHeader().GetAddr1(), tid),
513  GetBaBufferSize(peekedItem->GetOriginal()->GetHeader().GetAddr1(), tid)));
514 
515  // try A-MSDU aggregation
516  if (m_mac->GetHtSupported() && !recipient.IsBroadcast() &&
517  !peekedItem->HasSeqNoAssigned() && !peekedItem->IsFragment())
518  {
519  auto htFem = StaticCast<HtFrameExchangeManager>(qosFem);
520  mpdu = htFem->GetMsduAggregator()->GetNextAmsdu(peekedItem, txParams, availableTime);
521  }
522 
523  if (mpdu)
524  {
525  NS_LOG_DEBUG("Prepared an MPDU containing an A-MSDU");
526  }
527  // else aggregation was not attempted or failed
528  }
529 
530  if (!mpdu)
531  {
532  mpdu = peekedItem;
533  }
534 
535  // Assign a sequence number if this is not a fragment nor a retransmission
536  AssignSequenceNumber(mpdu);
537  NS_LOG_DEBUG("Got MPDU from EDCA queue: " << *mpdu);
538 
539  return mpdu;
540 }
541 
542 void
544 {
545  NS_LOG_FUNCTION(this << *mpdu);
546 
547  if (!mpdu->IsFragment() && !mpdu->HasSeqNoAssigned())
548  {
549  // in case of 11be MLDs, sequence numbers refer to the MLD address
550  auto origMpdu = m_queue->GetOriginal(mpdu);
551  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor(&origMpdu->GetHeader());
552  mpdu->AssignSeqNo(sequence);
553  }
554 }
555 
556 void
557 QosTxop::NotifyChannelAccessed(uint8_t linkId, Time txopDuration)
558 {
559  NS_LOG_FUNCTION(this << +linkId << txopDuration);
560 
561  NS_ASSERT(txopDuration != Time::Min());
562  GetLink(linkId).startTxop = Simulator::Now();
563  GetLink(linkId).txopDuration = txopDuration;
565 }
566 
567 bool
568 QosTxop::IsTxopStarted(uint8_t linkId) const
569 {
570  auto& link = GetLink(linkId);
571  NS_LOG_FUNCTION(this << !link.startTxop.IsZero());
572  return (!link.startTxop.IsZero());
573 }
574 
575 void
577 {
578  NS_LOG_FUNCTION(this << +linkId);
579  auto& link = GetLink(linkId);
580 
581  if (link.startTxop.IsStrictlyPositive())
582  {
583  NS_LOG_DEBUG("Terminating TXOP. Duration = " << Simulator::Now() - link.startTxop);
584  m_txopTrace(link.startTxop, Simulator::Now() - link.startTxop, linkId);
585  }
586  link.startTxop = Seconds(0);
588 }
589 
590 Time
591 QosTxop::GetRemainingTxop(uint8_t linkId) const
592 {
593  auto& link = GetLink(linkId);
594  NS_ASSERT(link.startTxop.IsStrictlyPositive());
595 
596  Time remainingTxop = link.txopDuration;
597  remainingTxop -= (Simulator::Now() - link.startTxop);
598  if (remainingTxop.IsStrictlyNegative())
599  {
600  remainingTxop = Seconds(0);
601  }
602  NS_LOG_FUNCTION(this << remainingTxop);
603  return remainingTxop;
604 }
605 
606 void
608 {
609  NS_LOG_FUNCTION(this << respHdr << recipient);
610  uint8_t tid = respHdr.GetTid();
611  if (respHdr.GetStatusCode().IsSuccess())
612  {
613  NS_LOG_DEBUG("block ack agreement established with " << recipient << " tid " << +tid);
614  // A (destination, TID) pair is "blocked" (i.e., no more packets are sent)
615  // when an Add BA Request is sent to the destination. However, when the
616  // Add BA Request timer expires, the (destination, TID) pair is "unblocked"
617  // and packets to the destination are sent again (under normal ack policy).
618  // Thus, there may be a packet needing to be retransmitted when the
619  // Add BA Response is received. In this case, the starting sequence number
620  // shall be set equal to the sequence number of such packet.
621  uint16_t startingSeq = m_txMiddle->GetNextSeqNumberByTidAndAddress(tid, recipient);
622  auto peekedItem = m_queue->PeekByTidAndAddress(tid, recipient);
623  if (peekedItem && peekedItem->GetHeader().IsRetry())
624  {
625  startingSeq = peekedItem->GetHeader().GetSequenceNumber();
626  }
627  m_baManager->UpdateOriginatorAgreement(respHdr, recipient, startingSeq);
628  }
629  else
630  {
631  NS_LOG_DEBUG("discard ADDBA response" << recipient);
632  m_baManager->NotifyOriginatorAgreementRejected(recipient, tid);
633  }
634 
635  for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
636  {
637  StartAccessIfNeeded(linkId);
638  }
639 }
640 
641 void
643 {
644  NS_LOG_FUNCTION(this << delBaHdr << recipient);
645  NS_LOG_DEBUG("received DELBA frame from=" << recipient);
646  m_baManager->DestroyOriginatorAgreement(recipient, delBaHdr->GetTid());
647 }
648 
649 void
651 {
652  NS_LOG_FUNCTION(this << recipient << tid);
653 
654  m_baManager->NotifyOriginatorAgreementNoReply(recipient, tid);
655  // the recipient has been "unblocked" and transmissions can resume using normal
656  // acknowledgment, hence start access (if needed) on all the links
657  for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
658  {
659  StartAccessIfNeeded(linkId);
660  }
661 }
662 
663 void
665 {
666  NS_ASSERT(mpdu->GetHeader().IsQosData());
667  // If there is an established BA agreement, store the packet in the queue of outstanding packets
668  if (m_mac->GetBaAgreementEstablishedAsOriginator(mpdu->GetHeader().GetAddr1(),
669  mpdu->GetHeader().GetQosTid()))
670  {
671  NS_ASSERT(mpdu->IsQueued());
672  NS_ASSERT(m_queue->GetAc() == mpdu->GetQueueAc());
673  m_baManager->StorePacket(m_queue->GetOriginal(mpdu));
674  }
675 }
676 
677 void
679 {
680  NS_LOG_FUNCTION(this << +threshold);
681  m_blockAckThreshold = threshold;
682  m_baManager->SetBlockAckThreshold(threshold);
683 }
684 
685 void
687 {
688  NS_LOG_FUNCTION(this << timeout);
690 }
691 
692 uint8_t
694 {
695  NS_LOG_FUNCTION(this);
696  return m_blockAckThreshold;
697 }
698 
699 uint16_t
701 {
703 }
704 
705 void
707 {
708  NS_LOG_FUNCTION(this << recipient << +tid);
709  // If agreement is still pending, ADDBA response is not received
710  if (auto agreement = m_baManager->GetAgreementAsOriginator(recipient, tid);
711  agreement && agreement->get().IsPending())
712  {
713  NotifyOriginatorAgreementNoReply(recipient, tid);
715  }
716 }
717 
718 void
719 QosTxop::ResetBa(Mac48Address recipient, uint8_t tid)
720 {
721  NS_LOG_FUNCTION(this << recipient << +tid);
722  // This function is scheduled when waiting for an ADDBA response. However,
723  // before this function is called, a DELBA request may arrive, which causes
724  // the agreement to be deleted. Hence, check if an agreement exists before
725  // notifying that the agreement has to be reset.
726  if (auto agreement = m_baManager->GetAgreementAsOriginator(recipient, tid);
727  agreement && !agreement->get().IsEstablished())
728  {
729  m_baManager->NotifyOriginatorAgreementReset(recipient, tid);
730  }
731 }
732 
733 void
735 {
736  NS_LOG_FUNCTION(this << addBaResponseTimeout);
737  m_addBaResponseTimeout = addBaResponseTimeout;
738 }
739 
740 Time
742 {
743  return m_addBaResponseTimeout;
744 }
745 
746 void
748 {
749  NS_LOG_FUNCTION(this << failedAddBaTimeout);
750  m_failedAddBaTimeout = failedAddBaTimeout;
751 }
752 
753 Time
755 {
756  return m_failedAddBaTimeout;
757 }
758 
759 bool
761 {
762  return true;
763 }
764 
765 AcIndex
767 {
768  return m_ac;
769 }
770 
771 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
void NotifyDiscardedMpdu(Ptr< const WifiMpdu > mpdu)
AttributeValue implementation for Boolean.
Definition: boolean.h:37
bool IsNull() const
Check for null implementation.
Definition: callback.h:572
auto Bind(BoundArgs &&... bargs)
Bind a variable number of arguments.
Definition: callback.h:560
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.
Definition: mgt-headers.h:1642
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.
Definition: mgt-headers.h:1761
uint8_t GetTid() const
Return the Traffic ID (TID).
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
void Unblock(Mac48Address dest, uint8_t tid)
Un-block the given destination address and TID (e.g.
void Block(Mac48Address dest, uint8_t tid)
Block the given destination address and TID from sending (e.g.
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:73
QosTxop(AcIndex ac=AC_UNDEF)
Constructor.
Definition: qos-txop.cc:106
std::unique_ptr< LinkEntity > CreateLinkEntity() const override
Create a LinkEntity object.
Definition: qos-txop.cc:142
~QosTxop() override
Definition: qos-txop.cc:123
uint8_t m_blockAckThreshold
the block ack threshold (use BA mechanism if number of packets in queue reaches this value.
Definition: qos-txop.h:470
Ptr< BlockAckManager > GetBaManager()
Get the Block Ack Manager associated with this QosTxop.
Definition: qos-txop.cc:261
Time m_failedAddBaTimeout
timeout after failed BA agreement
Definition: qos-txop.h:477
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:359
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:327
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:173
bool UseExplicitBarAfterMissedBlockAck() const
Return true if an explicit BlockAckRequest is sent after a missed BlockAck.
Definition: qos-txop.cc:304
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:223
Time GetAddBaResponseTimeout() const
Get the timeout for ADDBA response.
Definition: qos-txop.cc:741
AcIndex GetAccessCategory() const
Get the access category of this object.
Definition: qos-txop.cc:766
void AddBaResponseTimeout(Mac48Address recipient, uint8_t tid)
Callback when ADDBA response is not received after timeout.
Definition: qos-txop.cc:706
uint16_t GetBaBufferSize(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:267
void DoDispose() override
Destructor implementation.
Definition: qos-txop.cc:129
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:180
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:214
void StartMuEdcaTimerNow(uint8_t linkId)
Start the MU EDCA Timer for the given link.
Definition: qos-txop.cc:201
uint8_t GetBlockAckThreshold() const
Return the current threshold for block ack mechanism.
Definition: qos-txop.cc:693
void NotifyChannelReleased(uint8_t linkId) override
Called by the FrameExchangeManager to notify the completion of the transmissions.
Definition: qos-txop.cc:576
uint16_t GetNextSequenceNumberFor(const WifiMacHeader *hdr)
Return the next sequence number for the given header.
Definition: qos-txop.cc:321
uint16_t GetBlockAckInactivityTimeout() const
Get the BlockAck inactivity timeout.
Definition: qos-txop.cc:700
TxopTracedCallback m_txopTrace
TXOP trace callback.
Definition: qos-txop.h:488
virtual Time GetRemainingTxop(uint8_t linkId) const
Return the remaining duration in the current TXOP on the given link.
Definition: qos-txop.cc:591
AcIndex m_ac
the access category
Definition: qos-txop.h:467
void SetDroppedMpduCallback(DroppedMpdu callback) override
Definition: qos-txop.cc:165
bool m_useExplicitBarAfterMissedBlockAck
flag whether explicit BlockAckRequest should be sent upon missed BlockAck Response
Definition: qos-txop.h:478
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:187
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:650
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:154
void ResetBa(Mac48Address recipient, uint8_t tid)
Reset BA agreement after BA negotiation failed.
Definition: qos-txop.cc:719
Time GetFailedAddBaTimeout() const
Get the timeout for failed BA agreement.
Definition: qos-txop.cc:754
void GotAddBaResponse(const MgtAddBaResponseHeader &respHdr, Mac48Address recipient)
Event handler when an ADDBA response is received.
Definition: qos-txop.cc:607
static TypeId GetTypeId()
Get the type ID.
Definition: qos-txop.cc:59
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:543
void SetFailedAddBaTimeout(Time failedAddBaTimeout)
Set the timeout for failed BA agreement.
Definition: qos-txop.cc:747
uint16_t m_blockAckInactivityTimeout
the BlockAck inactivity timeout value (in TUs, i.e.
Definition: qos-txop.h:474
QosLinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: qos-txop.cc:148
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:474
void SetBlockAckThreshold(uint8_t threshold)
Set threshold for block ack mechanism.
Definition: qos-txop.cc:678
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:333
void GotDelBaFrame(const MgtDelBaHeader *delBaHdr, Mac48Address recipient)
Event handler when a DELBA frame is received.
Definition: qos-txop.cc:642
void SetBlockAckInactivityTimeout(uint16_t timeout)
Set the BlockAck inactivity timeout.
Definition: qos-txop.cc:686
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:480
void CompleteMpduTx(Ptr< WifiMpdu > mpdu)
Stores an MPDU (part of an A-MPDU) in block ack agreement (i.e.
Definition: qos-txop.cc:664
void SetAddBaResponseTimeout(Time addBaResponseTimeout)
Set the timeout to wait for ADDBA response.
Definition: qos-txop.cc:734
bool HasFramesToTransmit(uint8_t linkId) override
Check if the Txop has frames to transmit over the given link.
Definition: qos-txop.cc:310
uint16_t GetBaStartingSequence(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:273
bool IsQosTxop() const override
Check for QoS TXOP.
Definition: qos-txop.cc:760
Ptr< WifiMpdu > PrepareBlockAckRequest(Mac48Address recipient, uint8_t tid) const
Definition: qos-txop.cc:279
Ptr< QosBlockedDestinations > m_qosBlockedDestinations
the QoS blocked destinations
Definition: qos-txop.h:468
Time m_addBaResponseTimeout
timeout for ADDBA response
Definition: qos-txop.h:476
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:557
void SetMuEdcaTimer(Time timer, uint8_t linkId)
Set the MU EDCA Timer for the given link.
Definition: qos-txop.cc:194
Ptr< BlockAckManager > m_baManager
the block ack manager
Definition: qos-txop.h:469
virtual bool IsTxopStarted(uint8_t linkId) const
Return true if a TXOP has started on the given link.
Definition: qos-txop.cc:568
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
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:286
@ MS
millisecond
Definition: nstime.h:117
bool IsStrictlyNegative() const
Exactly equivalent to t < 0.
Definition: nstime.h:341
AttributeValue implementation for Time.
Definition: nstime.h:1423
Handle packet fragmentation and retransmissions for data and management frames.
Definition: txop.h:71
virtual void StartAccessIfNeeded(uint8_t linkId)
Request access from Txop on the given link if needed.
Definition: txop.cc:544
Ptr< WifiMac > m_mac
the wifi MAC
Definition: txop.h:516
Ptr< WifiMacQueue > m_queue
the wifi MAC queue
Definition: txop.h:514
void DoDispose() override
Destructor implementation.
Definition: txop.cc:157
uint32_t GetMinCw() const
Return the minimum contention window size.
Definition: txop.cc:404
virtual void NotifyChannelReleased(uint8_t linkId)
Called by the FrameExchangeManager to notify the completion of the transmissions.
Definition: txop.cc:585
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: txop.cc:174
DroppedMpdu m_droppedMpduCallback
the dropped MPDU callback
Definition: txop.h:513
virtual void SetDroppedMpduCallback(DroppedMpdu callback)
Definition: txop.cc:209
Ptr< MacTxMiddle > m_txMiddle
the MacTxMiddle
Definition: txop.h:515
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:578
uint8_t GetAifsn() const
Return the number of slots that make up an AIFS.
Definition: txop.cc:450
uint32_t GetMaxCw() const
Return the maximum contention window size.
Definition: txop.cc:427
uint8_t GetNLinks() const
Get the number of links.
Definition: txop.cc:182
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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.
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:840
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
Definition: wifi-mac.cc:1236
bool GetHtSupported() const
Return whether the device supports HT.
Definition: wifi-mac.cc:1365
Mac48Address GetLocalAddress(const Mac48Address &remoteAddr) const
Get the local MAC address used to communicate with a remote STA.
Definition: wifi-mac.cc:1249
OriginatorAgreementOptConstRef GetBaAgreementEstablishedAsOriginator(Mac48Address recipient, uint8_t tid) const
Definition: wifi-mac.cc:1283
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:846
This queue implements the timeout procedure described in (Section 9.19.2.6 "Retransmit procedures" pa...
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 > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
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:231
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:46
#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 ",...
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition: object.h:579
#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:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
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:186
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:72
address
Definition: first.py:40
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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:707
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
@ WIFI_MAC_CTL_BACKREQ
@ WIFI_QOSDATA_UNICAST_QUEUE
std::tuple< WifiContainerQueueType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, Address, TID) identifying a container queue.
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:119
@ WIFI_MAC_DROP_QOS_OLD_PACKET
Definition: wifi-mac.h:79
ns3::Time timeout