A Discrete-Event Network Simulator
API
qos-txop.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2006, 2009 INRIA
4  * Copyright (c) 2009 MIRKO BANCHI
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  * Mirko Banchi <mk.banchi@gmail.com>
21  * Stefano Avallone <stavalli@unina.it>
22  */
23 
24 #include "ns3/log.h"
25 #include "ns3/pointer.h"
26 #include "ns3/simulator.h"
27 #include "ns3/random-variable-stream.h"
28 #include "qos-txop.h"
29 #include "channel-access-manager.h"
30 #include "mac-tx-middle.h"
31 #include "mgt-headers.h"
32 #include "wifi-mac-trailer.h"
33 #include "wifi-mac-queue.h"
34 #include "mac-low.h"
37 #include "msdu-aggregator.h"
38 #include "mpdu-aggregator.h"
39 #include "ctrl-headers.h"
40 #include "wifi-phy.h"
41 
42 #undef NS_LOG_APPEND_CONTEXT
43 #define NS_LOG_APPEND_CONTEXT if (m_low != 0) { std::clog << "[mac=" << m_low->GetAddress () << "] "; }
44 
45 namespace ns3 {
46 
47 NS_LOG_COMPONENT_DEFINE ("QosTxop");
48 
50 
51 TypeId
53 {
54  static TypeId tid = TypeId ("ns3::QosTxop")
55  .SetParent<ns3::Txop> ()
56  .SetGroupName ("Wifi")
57  .AddConstructor<QosTxop> ()
58  .AddAttribute ("UseExpliciteBarAfterMissedBlockAck",
59  "Specify whether explicit Block Ack Request should be sent upon missed Block Ack Response.",
60  BooleanValue (true),
63  .AddAttribute ("AddBaResponseTimeout",
64  "The timeout to wait for ADDBA response after the ACK to "
65  "ADDBA request is received.",
66  TimeValue (MilliSeconds (1)),
69  MakeTimeChecker ())
70  .AddAttribute ("FailedAddBaTimeout",
71  "The timeout after a failed BA agreement. During this "
72  "timeout, the originator resumes sending packets using normal "
73  "MPDU. After that, BA agreement is reset and the originator "
74  "will retry BA negotiation.",
75  TimeValue (MilliSeconds (200)),
78  MakeTimeChecker ())
79  .AddAttribute ("BlockAckManager",
80  "The BlockAckManager object.",
81  PointerValue (),
83  MakePointerChecker<BlockAckManager> ())
84  .AddTraceSource ("TxopTrace",
85  "Trace source for txop start and duration times",
87  "ns3::TracedValueCallback::Time")
88  ;
89  return tid;
90 }
91 
93  : m_typeOfStation (STA),
94  m_blockAckType (COMPRESSED_BLOCK_ACK),
95  m_startTxop (Seconds (0)),
96  m_isAccessRequestedForRts (false),
97  m_currentIsFragmented (false)
98 {
99  NS_LOG_FUNCTION (this);
100  m_qosBlockedDestinations = Create<QosBlockedDestinations> ();
101  m_baManager = CreateObject<BlockAckManager> ();
102  m_baManager->SetQueue (m_queue);
103  m_baManager->SetBlockAckType (m_blockAckType);
106  m_baManager->SetTxOkCallback (MakeCallback (&QosTxop::BaTxOk, this));
107  m_baManager->SetTxFailedCallback (MakeCallback (&QosTxop::BaTxFailed, this));
108 }
109 
111 {
112  NS_LOG_FUNCTION (this);
113 }
114 
115 void
117 {
118  NS_LOG_FUNCTION (this);
119  m_baManager = 0;
121  Txop::DoDispose ();
122 }
123 
124 bool
126 {
127  return m_baManager->ExistsAgreementInState (address, tid, OriginatorBlockAckAgreement::ESTABLISHED);
128 }
129 
130 uint16_t
132 {
133  return m_baManager->GetRecipientBufferSize (address, tid);
134 }
135 
136 uint16_t
138 {
139  return m_baManager->GetOriginatorStartingSequence (address, tid);
140 }
141 
142 void
144 {
145  Txop::SetWifiRemoteStationManager (remoteManager);
146  NS_LOG_FUNCTION (this << remoteManager);
147  m_baManager->SetWifiRemoteStationManager (m_stationManager);
148 }
149 
150 void
152 {
153  NS_LOG_FUNCTION (this << +type);
154  m_typeOfStation = type;
155 }
156 
159 {
160  return m_typeOfStation;
161 }
162 
163 uint16_t
165 {
166  return m_txMiddle->GetNextSequenceNumberFor (hdr);
167 }
168 
169 uint16_t
171 {
172  return m_txMiddle->PeekNextSequenceNumberFor (hdr);
173 }
174 
175 bool
177 {
178  NS_LOG_FUNCTION (this << *mpdu);
179 
180  if (!mpdu->GetHeader ().IsQosData ())
181  {
182  return false;
183  }
184 
185  Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
186  uint8_t tid = mpdu->GetHeader ().GetQosTid ();
187 
188  if (!GetBaAgreementEstablished (recipient, tid))
189  {
190  return false;
191  }
192 
193  if (QosUtilsIsOldPacket (GetBaStartingSequence (recipient, tid),
194  mpdu->GetHeader ().GetSequenceNumber ()))
195  {
196  return true;
197  }
198  return false;
199 }
200 
202 QosTxop::PeekNextFrame (uint8_t tid, Mac48Address recipient)
203 {
204  NS_LOG_FUNCTION (this);
205  WifiMacQueue::ConstIterator it = WifiMacQueue::EMPTY;
206 
207  // lambda to peek the next frame
208  auto peek = [this, &tid, &recipient, &it] (Ptr<WifiMacQueue> queue)
209  {
210  if (tid == 8 && recipient.IsBroadcast ()) // undefined TID and recipient
211  {
212  return queue->PeekFirstAvailable (m_qosBlockedDestinations, it);
213  }
214  return queue->PeekByTidAndAddress (tid, recipient, it);
215  };
216 
217  // check if there is a packet in the BlockAckManager retransmit queue
218  it = peek (m_baManager->GetRetransmitQueue ());
219  // remove old packets
220  while (it != m_baManager->GetRetransmitQueue ()->end () && IsQosOldPacket (*it))
221  {
222  NS_LOG_DEBUG ("removing an old packet from BlockAckManager retransmit queue: " << **it);
223  it = m_baManager->GetRetransmitQueue ()->Remove (it);
224  it = peek (m_baManager->GetRetransmitQueue ());
225  }
226  if (it != m_baManager->GetRetransmitQueue ()->end ())
227  {
228  NS_LOG_DEBUG ("packet peeked from BlockAckManager retransmit queue: " << **it);
229  return *it;
230  }
231 
232  // otherwise, check if there is a packet in the EDCA queue
233  it = WifiMacQueue::EMPTY;
234  it = peek (m_queue);
235  if (it != m_queue->end ())
236  {
237  // peek the next sequence number and check if it is within the transmit window
238  // in case of QoS data frame
239  uint16_t sequence = m_txMiddle->PeekNextSequenceNumberFor (&(*it)->GetHeader ());
240  if ((*it)->GetHeader ().IsQosData ())
241  {
242  Mac48Address recipient = (*it)->GetHeader ().GetAddr1 ();
243  uint8_t tid = (*it)->GetHeader ().GetQosTid ();
244 
245  if (GetBaAgreementEstablished (recipient, tid)
246  && !IsInWindow (sequence, GetBaStartingSequence (recipient, tid), GetBaBufferSize (recipient, tid)))
247  {
248  NS_LOG_DEBUG ("packet beyond the end of the current transmit window");
249  return 0;
250  }
251  }
252 
253  WifiMacHeader hdr = (*it)->GetHeader ();
254  hdr.SetSequenceNumber (sequence);
255  hdr.SetFragmentNumber (0);
256  hdr.SetNoMoreFragments ();
257  hdr.SetNoRetry ();
258  Ptr<const WifiMacQueueItem> item = Create<const WifiMacQueueItem> ((*it)->GetPacket (), hdr, (*it)->GetTimeStamp ());
259  NS_LOG_DEBUG ("packet peeked from EDCA queue: " << *item);
260  return item;
261  }
262 
263  return 0;
264 }
265 
268  bool aggregate, uint32_t ampduSize, Time ppduDurationLimit)
269 {
270  NS_LOG_FUNCTION (this << peekedItem << txVector << ampduSize << ppduDurationLimit);
271  NS_ASSERT (peekedItem != 0);
272 
273  // do not dequeue the frame if it is a QoS data frame that does not meet the
274  // max A-MPDU size limit (if applicable) or the duration limit (if applicable)
275  if (peekedItem->GetHeader ().IsQosData () &&
276  !m_low->IsWithinSizeAndTimeLimits (peekedItem, txVector, ampduSize, ppduDurationLimit))
277  {
278  return 0;
279  }
280 
281  Mac48Address recipient = peekedItem->GetHeader ().GetAddr1 ();
284  WifiMacQueue::ConstIterator testIt;
285 
286  // the packet can only have been peeked from the Block Ack manager retransmit
287  // queue if:
288  // - the peeked packet is a QoS Data frame AND
289  // - the peeked packet is not a broadcast frame AND
290  // - an agreement has been established
291  if (peekedItem->GetHeader ().IsQosData () && !recipient.IsBroadcast ()
292  && GetBaAgreementEstablished (recipient, peekedItem->GetHeader ().GetQosTid ()))
293  {
294  uint8_t tid = peekedItem->GetHeader ().GetQosTid ();
295  testIt = m_baManager->GetRetransmitQueue ()->PeekByTidAndAddress (tid, recipient);
296 
297  if (testIt != m_baManager->GetRetransmitQueue ()->end ())
298  {
299  testItem = *testIt;
300  // if not null, the test packet must equal the peeked packet
301  NS_ASSERT (testItem->GetPacket () == peekedItem->GetPacket ());
302  // we should not be asked to dequeue an old packet
304  testItem->GetHeader ().GetSequenceNumber ()));
305  item = m_baManager->GetRetransmitQueue ()->Dequeue (testIt);
306  NS_LOG_DEBUG ("dequeued from BA manager queue: " << *item);
307  return item;
308  }
309  }
310 
311  // the packet has been peeked from the EDCA queue.
312  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&peekedItem->GetHeader ());
313 
314  // If it is a QoS Data frame and it is not a broadcast frame, attempt A-MSDU
315  // aggregation if aggregate is true
316  if (peekedItem->GetHeader ().IsQosData ())
317  {
318  uint8_t tid = peekedItem->GetHeader ().GetQosTid ();
319  testIt = m_queue->PeekByTidAndAddress (tid, recipient);
320 
321  NS_ASSERT (testIt != m_queue->end () && (*testIt)->GetPacket () == peekedItem->GetPacket ());
322 
323  // check if the peeked packet is within the transmit window
324  if (GetBaAgreementEstablished (recipient, tid)
325  && !IsInWindow (sequence, GetBaStartingSequence (recipient, tid), GetBaBufferSize (recipient, tid)))
326  {
327  NS_LOG_DEBUG ("packet beyond the end of the current transmit window");
328  return 0;
329  }
330 
331  // try A-MSDU aggregation
332  if (m_low->GetMsduAggregator () != 0 && !recipient.IsBroadcast () && aggregate)
333  {
334  item = m_low->GetMsduAggregator ()->GetNextAmsdu (recipient, tid, txVector, ampduSize, ppduDurationLimit);
335  }
336 
337  if (item != 0)
338  {
339  NS_LOG_DEBUG ("tx unicast A-MSDU");
340  }
341  else // aggregation was not attempted or failed
342  {
343  item = m_queue->Dequeue (testIt);
344  }
345  }
346  else
347  {
348  // the peeked packet is a non-QoS Data frame (e.g., a DELBA Request), hence
349  // it was not peeked by TID, hence it must be the head of the queue
350  item = m_queue->DequeueFirstAvailable (m_qosBlockedDestinations);
351  NS_ASSERT (item != 0 && item->GetPacket () == peekedItem->GetPacket ());
352  }
353 
354  // Assign a sequence number to the MSDU or A-MSDU dequeued from the EDCA queue
355  NS_ASSERT (item != 0);
356  item->GetHeader ().SetSequenceNumber (sequence);
357  item->GetHeader ().SetFragmentNumber (0);
358  item->GetHeader ().SetNoMoreFragments ();
359  item->GetHeader ().SetNoRetry ();
360  NS_LOG_DEBUG ("dequeued from EDCA queue: " << *item);
361 
362  return item;
363 }
364 
367 {
368  NS_LOG_FUNCTION (this << *frame);
369 
371  Mac48Address recipient = frame->GetHeader ().GetAddr1 ();
372 
373  params.DisableNextData ();
374 
375  // broadcast frames
376  if (recipient.IsBroadcast ())
377  {
378  params.DisableRts ();
379  params.DisableAck ();
380  return params;
381  }
382  if (frame->GetHeader ().IsMgt ())
383  {
384  params.DisableRts ();
385  params.EnableAck ();
386  return params;
387  }
388 
389  // Enable/disable RTS
390  if (!frame->GetHeader ().IsBlockAckReq ()
391  && m_stationManager->NeedRts (recipient, &frame->GetHeader (),
392  frame->GetPacket (), m_low->GetDataTxVector (frame))
393  && !m_low->IsCfPeriod ())
394  {
395  params.EnableRts ();
396  }
397  else
398  {
399  params.DisableRts ();
400  }
401 
402  uint8_t tid;
403  CtrlBAckRequestHeader baReqHdr;
404  if (frame->GetHeader ().IsBlockAckReq ())
405  {
406  frame->GetPacket ()->PeekHeader (baReqHdr);
407  tid = baReqHdr.GetTidInfo ();
408  }
409  else if (frame->GetHeader ().IsQosData ())
410  {
411  tid = frame->GetHeader ().GetQosTid ();
412  }
413  else
414  {
415  NS_ABORT_MSG ("Unexpected type of frame");
416  }
417 
418  // Select ack technique.
419  if (frame->GetHeader ().IsQosData () && !GetBaAgreementEstablished (recipient, tid))
420  {
421  // normal ack in case of QoS data frame with no agreement established
422  // TODO We should also arrive here in case of block ack request with delayed
423  // block ack, which is currently unsupported
424  params.EnableAck ();
425  }
426  else if (frame->GetHeader ().IsQosData () && frame->GetHeader ().IsQosBlockAck ())
427  {
428  // no ack after a QoS data frame with explicit block ack policy
429  params.DisableAck ();
430  }
431  else
432  {
433  // assume a block ack variant. Later, if this frame is not aggregated,
434  // the acknowledgment type will be switched to normal ack
436  {
437  params.EnableBasicBlockAck ();
438  }
440  {
441  if (GetBaBufferSize (recipient, tid) > 64)
442  {
444  }
445  else
446  {
447  params.EnableCompressedBlockAck ();
448  }
449  }
451  {
452  NS_FATAL_ERROR ("Multi-tid block ack is not supported");
453  }
454  }
455 
456  return params;
457 }
458 
459 void
461 {
462  NS_LOG_FUNCTION (this);
464  m_accessRequested = false;
467  // discard the current packet if it is a QoS Data frame with expired lifetime
468  if (m_currentPacket != 0 && m_currentHdr.IsQosData ()
469  && (m_currentPacketTimestamp + m_queue->GetMaxDelay () < Simulator::Now ()))
470  {
471  NS_LOG_DEBUG ("the lifetime of current packet expired");
472  m_currentPacket = 0;
473  }
474  if (m_currentPacket == 0)
475  {
476  if (m_baManager->HasBar (m_currentBar))
477  {
479  return;
480  }
482  if (peekedItem == 0)
483  {
484  NS_LOG_DEBUG ("no packets available for transmission");
485  return;
486  }
487  // check if a Block Ack agreement needs to be established
488  m_currentHdr = peekedItem->GetHeader ();
489  m_currentPacket = peekedItem->GetPacket ();
492  && (!m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
494  && SetupBlockAckIfNeeded ())
495  {
496  return;
497  }
498 
500  Time ppduDurationLimit = Seconds (0);
501 
502  // compute the limit on the PPDU duration due to the TXOP duration, if any
503  if (peekedItem->GetHeader ().IsQosData () && GetTxopLimit ().IsStrictlyPositive ())
504  {
506  ppduDurationLimit = GetTxopRemaining () - m_low->CalculateOverheadTxTime (peekedItem, params);
507  }
508 
509  // dequeue the peeked item if it fits within the TXOP duration, if any
510  Ptr<WifiMacQueueItem> item = DequeuePeekedFrame (peekedItem, m_low->GetDataTxVector (peekedItem),
511  !NeedFragmentation (), 0, ppduDurationLimit);
512 
513  if (item == 0)
514  {
515  NS_LOG_DEBUG ("Not enough time in the current TXOP");
516  return;
517  }
518  m_currentPacket = item->GetPacket ();
519  m_currentHdr = item->GetHeader ();
520  m_currentPacketTimestamp = item->GetTimeStamp ();
521  NS_ASSERT (m_currentPacket != 0);
522 
523  m_fragmentNumber = 0;
525  {
526  VerifyBlockAck ();
527  }
528  }
529  Ptr<WifiMacQueueItem> mpdu = Create <WifiMacQueueItem> (m_currentPacket, m_currentHdr,
531  if (m_currentHdr.GetAddr1 ().IsGroup ())
532  {
536  NS_LOG_DEBUG ("tx broadcast");
537  m_low->StartTransmission (mpdu, m_currentParams, this);
538  }
540  {
542  }
543  else
544  {
546 
547  // check if the current frame meets the QoS TXOP Limit, if any
548  if (mpdu->GetHeader ().IsQosData () && GetTxopLimit ().IsStrictlyPositive () &&
549  m_low->CalculateOverallTxTime (mpdu->GetPacket (), &mpdu->GetHeader (),
551  {
552  NS_LOG_DEBUG ("Not enough time in the current TXOP");
553  return;
554  }
555 
556  //With COMPRESSED_BLOCK_ACK fragmentation must be avoided.
558  || (m_currentHdr.IsData () && !m_currentHdr.IsQosData ()))
560  && NeedFragmentation ())
561  {
562  m_currentIsFragmented = true;
564  WifiMacHeader hdr;
565  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
566  if (IsLastFragment ())
567  {
568  NS_LOG_DEBUG ("fragmenting last fragment size=" << fragment->GetSize ());
570  }
571  else
572  {
573  NS_LOG_DEBUG ("fragmenting size=" << fragment->GetSize ());
575  }
576  m_low->StartTransmission (Create<WifiMacQueueItem> (fragment, hdr),
577  m_currentParams, this);
578  }
579  else
580  {
581  m_currentIsFragmented = false;
582  m_low->StartTransmission (mpdu, m_currentParams, this);
584  {
585  CompleteTx ();
586  }
587  }
588  }
589 }
590 
592 {
593  NS_LOG_FUNCTION (this);
594  bool resetDcf = false;
595  // If an internal collision is experienced, the frame involved may still
596  // be sitting in the queue, and m_currentPacket may still be null.
597  Ptr<const Packet> packet;
598  WifiMacHeader header;
599  if (m_currentPacket == 0)
600  {
602  if (item)
603  {
604  packet = item->GetPacket ();
605  header = item->GetHeader ();
606  }
607  }
608  else
609  {
610  packet = m_currentPacket;
611  header = m_currentHdr;
612  }
613  if (packet != 0)
614  {
616  {
617  if (!NeedRtsRetransmission (packet, header))
618  {
619  resetDcf = true;
620  m_stationManager->ReportFinalRtsFailed (header.GetAddr1 (), &header);
621  }
622  else
623  {
624  m_stationManager->ReportRtsFailed (header.GetAddr1 (), &header);
625  }
626  }
627  else if (header.GetAddr1 () == Mac48Address::GetBroadcast ())
628  {
629  resetDcf = false;
630  }
631  else
632  {
633  if (!NeedDataRetransmission (packet, header))
634  {
635  resetDcf = true;
636  m_stationManager->ReportFinalDataFailed (header.GetAddr1 (), &header, packet->GetSize ());
637  }
638  else
639  {
640  m_stationManager->ReportDataFailed (header.GetAddr1 (), &header, packet->GetSize ());
641  }
642  }
643  if (resetDcf)
644  {
645  NS_LOG_DEBUG ("reset DCF");
646  if (!m_txFailedCallback.IsNull ())
647  {
648  m_txFailedCallback (header);
649  }
650  //to reset the dcf.
651  if (m_currentPacket)
652  {
653  NS_LOG_DEBUG ("Discarding m_currentPacket");
654  m_currentPacket = 0;
655  }
656  else
657  {
658  NS_LOG_DEBUG ("Dequeueing and discarding head of queue");
659  m_queue->Remove ();
660  }
661  ResetCw ();
662  }
663  else
664  {
665  UpdateFailedCw ();
666  }
667  }
668  m_backoff = m_rng->GetInteger (0, GetCw ());
672 }
673 
674 void
676 {
677  NS_LOG_FUNCTION (this);
678  m_backoff = m_rng->GetInteger (0, GetCw ());
682 }
683 
684 void
686 {
687  NS_LOG_FUNCTION (this);
688  NS_LOG_DEBUG ("missed cts");
689  NS_ASSERT (!mpduList.empty ());
691  {
692  NS_LOG_DEBUG ("Cts Fail");
694  if (!m_txFailedCallback.IsNull ())
695  {
697  }
698  for (auto& mpdu : mpduList)
699  {
700  m_baManager->NotifyDiscardedMpdu (mpdu);
701  }
702  //to reset the dcf.
703  m_currentPacket = 0;
704  ResetCw ();
705  m_cwTrace = GetCw ();
706  }
707  else
708  {
709  UpdateFailedCw ();
710  m_cwTrace = GetCw ();
711  // if a BA agreement is established, store the MPDUs in the block ack manager
712  // retransmission queue. Otherwise, this QosTxop will handle the retransmission
713  // of the (single) frame
714  if (mpduList.size () > 1 ||
715  (mpduList.front ()->GetHeader ().IsQosData ()
716  && GetBaAgreementEstablished (mpduList.front ()->GetHeader ().GetAddr1 (),
717  mpduList.front ()->GetHeader ().GetQosTid ())))
718  {
719  for (auto it = mpduList.rbegin (); it != mpduList.rend (); it++)
720  {
721  m_baManager->GetRetransmitQueue ()->PushFront (*it);
722  }
723  m_currentPacket = 0;
724  }
725  }
726  m_backoff = m_rng->GetInteger (0, GetCw ());
730 }
731 
732 void
734 {
735  NS_LOG_FUNCTION (this);
738  || m_currentHdr.IsQosAmsdu ())
739  {
740  NS_LOG_DEBUG ("got ack. tx done.");
741  if (!m_txOkCallback.IsNull ())
742  {
744  }
745 
746  if (m_currentHdr.IsAction ())
747  {
748  WifiActionHeader actionHdr;
750  p->RemoveHeader (actionHdr);
751  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK)
752  {
754  {
755  MgtDelBaHeader delBa;
756  p->PeekHeader (delBa);
757  if (delBa.IsByOriginator ())
758  {
759  m_baManager->DestroyAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
760  }
761  else
762  {
763  m_low->DestroyBlockAckAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
764  }
765  }
767  {
768  // Setup addba response timeout
769  MgtAddBaRequestHeader addBa;
770  p->PeekHeader (addBa);
773  m_currentHdr.GetAddr1 (), addBa.GetTid ());
774  }
775  }
776  }
778  {
779  // notify the BA manager that the current packet was acknowledged
780  m_baManager->NotifyGotAck (Create<const WifiMacQueueItem> (m_currentPacket, m_currentHdr,
782  }
783  m_currentPacket = 0;
784  ResetCw ();
785  }
786  else
787  {
788  NS_LOG_DEBUG ("got ack. tx not done, size=" << m_currentPacket->GetSize ());
789  }
790 }
791 
792 void
794 {
795  NS_LOG_FUNCTION (this);
796  NS_LOG_DEBUG ("missed ack");
798  {
799  NS_LOG_DEBUG ("Ack Fail");
802  if (!m_txFailedCallback.IsNull ())
803  {
805  }
806  if (m_currentHdr.IsAction ())
807  {
808  WifiActionHeader actionHdr;
809  m_currentPacket->PeekHeader (actionHdr);
810  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK)
811  {
812  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
813  if (m_baManager->ExistsAgreementInState (m_currentHdr.GetAddr1 (), tid, OriginatorBlockAckAgreement::PENDING))
814  {
815  NS_LOG_DEBUG ("No ACK after ADDBA request");
816  m_baManager->NotifyAgreementNoReply (m_currentHdr.GetAddr1 (), tid);
818  }
819  }
820  }
822  {
823  m_baManager->NotifyDiscardedMpdu (Create<const WifiMacQueueItem> (m_currentPacket, m_currentHdr));
824  }
825  m_currentPacket = 0;
826  ResetCw ();
827  m_cwTrace = GetCw ();
828  }
829  else
830  {
831  NS_LOG_DEBUG ("Retransmit");
836  {
837  // notify the BA manager that the current packet was not acknowledged
838  m_baManager->NotifyMissedAck (Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr,
840  // let the BA manager handle its retransmission
841  m_currentPacket = 0;
842  }
843  UpdateFailedCw ();
844  m_cwTrace = GetCw ();
845  }
846  m_backoff = m_rng->GetInteger (0, GetCw ());
850 }
851 
852 void
853 QosTxop::MissedBlockAck (uint8_t nMpdus)
854 {
855  NS_LOG_FUNCTION (this << +nMpdus);
856  /*
857  * If the BlockAck frame is lost, the originator may transmit a BlockAckReq
858  * frame to solicit an immediate BlockAck frame or it may retransmit the Data
859  * frames. (IEEE std 802.11-2016 sec. 10.24.7.7
860  */
861  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
863  {
864  m_stationManager->ReportAmpduTxStatus (m_currentHdr.GetAddr1 (), tid, 0, nMpdus, 0, 0);
865  }
867  {
868  if (NeedBarRetransmission ())
869  {
870  NS_LOG_DEBUG ("Retransmit block ack request");
872  {
874  UpdateFailedCw ();
875  m_cwTrace = GetCw ();
876  }
877  else // missed block ack after data frame with Implicit BAR Ack policy
878  {
879  m_baManager->ScheduleBlockAckReq (m_currentHdr.GetAddr1 (), tid);
880  m_currentPacket = 0;
881  }
882  }
883  else
884  {
885  NS_LOG_DEBUG ("Block Ack Request Fail");
886  //to reset the dcf.
887  m_baManager->DiscardOutstandingMpdus (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr));
888  m_currentPacket = 0;
889  ResetCw ();
890  m_cwTrace = GetCw ();
891  }
892  }
893  else
894  {
895  // implicit BAR and do not use BAR after missed block ack, hence try to retransmit data frames
897  {
898  NS_LOG_DEBUG ("Block Ack Fail");
899  if (!m_txFailedCallback.IsNull ())
900  {
902  }
903  if (m_currentHdr.IsAction ())
904  {
905  WifiActionHeader actionHdr;
906  m_currentPacket->PeekHeader (actionHdr);
907  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK)
908  {
909  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
910  if (m_baManager->ExistsAgreementInState (m_currentHdr.GetAddr1 (), tid, OriginatorBlockAckAgreement::PENDING))
911  {
912  NS_LOG_DEBUG ("No ACK after ADDBA request");
913  m_baManager->NotifyAgreementNoReply (m_currentHdr.GetAddr1 (), tid);
915  }
916  }
917  }
918  //to reset the dcf.
919  m_baManager->DiscardOutstandingMpdus (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr));
920  m_currentPacket = 0;
921  ResetCw ();
922  m_cwTrace = GetCw ();
923  }
924  else
925  {
926  NS_LOG_DEBUG ("Retransmit");
927  m_baManager->NotifyMissedBlockAck (m_currentHdr.GetAddr1 (), tid);
928  m_currentPacket = 0;
929  UpdateFailedCw ();
930  m_cwTrace = GetCw ();
931  }
932  }
933  m_backoff = m_rng->GetInteger (0, GetCw ());
937 }
938 
939 void
941 {
942  NS_LOG_FUNCTION (this);
943  if ((m_currentPacket != 0
944  // check first if the BA manager retransmit queue is empty, so that expired
945  // frames (if any) are removed and a Block Ack Request is scheduled to advance
946  // the starting sequence number of the transmit (and receiver) window
947  || m_baManager->HasPackets () || !m_queue->IsEmpty ())
948  && !IsAccessRequested ())
949  {
950  Ptr<const Packet> packet;
951  WifiMacHeader hdr;
952  if (m_currentPacket != 0)
953  {
954  packet = m_currentPacket;
955  hdr = m_currentHdr;
956  }
957  else
958  {
960  if (item)
961  {
962  packet = item->GetPacket ();
963  hdr = item->GetHeader ();
964  }
965  }
966  if (packet != 0)
967  {
969  m_low->GetDataTxVector (Create<const WifiMacQueueItem> (packet, hdr)));
970  }
971  else
972  {
974  }
976  }
977 }
978 
979 void
981 {
982  NS_LOG_FUNCTION (this);
983  if (m_currentPacket == 0
984  // check first if the BA manager retransmit queue is empty, so that expired
985  // frames (if any) are removed and a Block Ack Request is scheduled to advance
986  // the starting sequence number of the transmit (and receiver) window
987  && (m_baManager->HasPackets () || !m_queue->IsEmpty ())
988  && !IsAccessRequested ())
989  {
990  Ptr<const Packet> packet;
991  WifiMacHeader hdr;
993  if (item)
994  {
995  packet = item->GetPacket ();
996  hdr = item->GetHeader ();
997  }
998  if (packet != 0)
999  {
1001  m_low->GetDataTxVector (Create<const WifiMacQueueItem> (packet, hdr)));
1002  }
1003  else
1004  {
1005  m_isAccessRequestedForRts = false;
1006  }
1008  }
1009 }
1010 
1011 bool
1013 {
1014  uint8_t tid = 0;
1015  if (m_currentHdr.IsQosData ())
1016  {
1017  tid = m_currentHdr.GetQosTid ();
1018  }
1019  else if (m_currentHdr.IsBlockAckReq ())
1020  {
1021  CtrlBAckRequestHeader baReqHdr;
1022  m_currentPacket->PeekHeader (baReqHdr);
1023  tid = baReqHdr.GetTidInfo ();
1024  }
1025  else if (m_currentHdr.IsBlockAck ())
1026  {
1027  CtrlBAckResponseHeader baRespHdr;
1028  m_currentPacket->PeekHeader (baRespHdr);
1029  tid = baRespHdr.GetTidInfo ();
1030  }
1031  return m_baManager->NeedBarRetransmission (tid, m_currentHdr.GetAddr1 ());
1032 }
1033 
1034 void
1036 {
1037  NS_LOG_FUNCTION (this);
1038  NS_ASSERT (GetTxopLimit ().IsStrictlyPositive () && GetTxopRemaining ().IsStrictlyPositive ());
1039 
1040  m_currentPacket = 0;
1041  Ptr<const WifiMacQueueItem> nextFrame;
1042 
1043  // peek the next BlockAckReq, if any
1044  if (m_baManager->HasBar (m_currentBar, false))
1045  {
1046  WifiMacHeader hdr;
1049  nextFrame = Create<const WifiMacQueueItem> (m_currentBar.bar, hdr);
1050  }
1051  else
1052  {
1053  nextFrame = PeekNextFrame ();
1054  }
1055 
1056  if (nextFrame != 0)
1057  {
1059 
1060  if (GetTxopRemaining () >= m_low->CalculateOverallTxTime (nextFrame->GetPacket (), &nextFrame->GetHeader (), params))
1061  {
1062  if (nextFrame->GetHeader ().IsBlockAckReq ())
1063  {
1064  NS_LOG_DEBUG ("start next BlockAckReq within the current TXOP");
1065  m_baManager->HasBar (m_currentBar);
1067  return;
1068  }
1069 
1070  // check if a Block Ack agreement needs to be established
1071  m_currentHdr = nextFrame->GetHeader ();
1072  m_currentPacket = nextFrame->GetPacket ();
1075  && (!m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
1077  && SetupBlockAckIfNeeded ())
1078  {
1079  return;
1080  }
1081 
1082  // when dequeuing the peeked packet, A-MSDU aggregation is attempted if the
1083  // packet has been peeked from the EDCA queue. Thus, compute the max available
1084  // time for the transmission of the PPDU
1085  Time maxPpduDuration = GetTxopRemaining () - m_low->CalculateOverheadTxTime (nextFrame, params);
1086  NS_ASSERT (maxPpduDuration.IsPositive ());
1087 
1088  Ptr<WifiMacQueueItem> item = DequeuePeekedFrame (nextFrame, m_low->GetDataTxVector (nextFrame),
1089  true, 0, maxPpduDuration);
1090  NS_ASSERT (item != 0);
1091  NS_LOG_DEBUG ("start next packet " << *item << " within the current TXOP");
1092  m_currentPacket = item->GetPacket ();
1093  m_currentHdr = item->GetHeader ();
1094  m_currentPacketTimestamp = item->GetTimeStamp ();
1095  NS_ASSERT (m_currentPacket != 0);
1096 
1097  m_currentParams = params;
1099  m_fragmentNumber = 0;
1101  {
1102  VerifyBlockAck ();
1103  }
1104  GetLow ()->StartTransmission (item, m_currentParams, this);
1106  {
1107  CompleteTx ();
1108  }
1109  return;
1110  }
1111  }
1112 
1113  // terminate TXOP because no (suitable) frame was found
1114  TerminateTxop ();
1115 }
1116 
1117 void
1119 {
1120  NS_LOG_FUNCTION (this);
1121  if (GetTxopLimit ().IsStrictlyPositive ())
1122  {
1123  NS_LOG_DEBUG ("Terminating TXOP. Duration = " << Simulator::Now () - m_startTxop);
1125  }
1126  m_cwTrace = GetCw ();
1127  m_backoff = m_rng->GetInteger (0, GetCw ());
1131 }
1132 
1133 Time
1135 {
1136  Time remainingTxop = GetTxopLimit ();
1137  remainingTxop -= (Simulator::Now () - m_startTxop);
1138  if (remainingTxop.IsStrictlyNegative ())
1139  {
1140  remainingTxop = Seconds (0);
1141  }
1142  NS_LOG_FUNCTION (this << remainingTxop);
1143  return remainingTxop;
1144 }
1145 
1146 void
1148 {
1149  NS_LOG_FUNCTION (this);
1150  NS_LOG_DEBUG ("a transmission that did not require an ACK just finished");
1151  m_currentPacket = 0;
1152  ResetCw ();
1153  TerminateTxop ();
1154 }
1155 
1156 bool
1158 {
1159  NS_LOG_FUNCTION (this);
1164  && m_currentHdr.IsQosData ()
1166  && GetLow ()->GetMpduAggregator () != 0
1167  && GetLow ()->GetMpduAggregator ()->GetMaxAmpduSize (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr),
1169  {
1170  //MSDU is not fragmented when it is transmitted using an HT-immediate or
1171  //HT-delayed Block Ack agreement or when it is carried in an A-MPDU.
1172  return false;
1173  }
1174  bool needTxopFragmentation = false;
1176  {
1177  needTxopFragmentation = (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams) > GetTxopLimit ());
1178  }
1179  return (needTxopFragmentation || m_stationManager->NeedFragmentation (m_currentHdr.GetAddr1 (), &m_currentHdr, m_currentPacket));
1180 }
1181 
1182 bool
1184 {
1185  if (GetTxopLimit ().IsZero ())
1186  {
1187  return false;
1188  }
1191  {
1192  return true;
1193  }
1194  return false;
1195 }
1196 
1197 uint32_t
1199 {
1200  Time txopDuration = GetTxopLimit ();
1201  if (txopDuration.IsZero ())
1202  {
1203  return 0;
1204  }
1205  uint32_t maxSize = m_currentPacket->GetSize ();
1206  uint32_t minSize = 0;
1207  uint32_t size = 0;
1208  bool found = false;
1209  while (!found)
1210  {
1211  size = (minSize + ((maxSize - minSize) / 2));
1212  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) > txopDuration)
1213  {
1214  maxSize = size;
1215  }
1216  else
1217  {
1218  minSize = size;
1219  }
1220  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) <= txopDuration
1221  && GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size + 1) > txopDuration)
1222  {
1223  found = true;
1224  }
1225  }
1226  NS_ASSERT (size != 0);
1227  return size;
1228 }
1229 
1230 uint32_t
1232 {
1233  uint32_t fragmentSize = GetTxopFragmentSize ();
1234  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1235  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1236  {
1237  nFragments++;
1238  }
1239  NS_LOG_DEBUG ("GetNTxopFragment returning " << nFragments);
1240  return nFragments;
1241 }
1242 
1243 uint32_t
1244 QosTxop::GetTxopFragmentOffset (uint32_t fragmentNumber) const
1245 {
1246  if (fragmentNumber == 0)
1247  {
1248  return 0;
1249  }
1250  uint32_t offset = 0;
1251  uint32_t fragmentSize = GetTxopFragmentSize ();
1252  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1253  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1254  {
1255  nFragments++;
1256  }
1257  if (fragmentNumber < nFragments)
1258  {
1259  offset = (fragmentNumber * fragmentSize);
1260  }
1261  else
1262  {
1263  NS_ASSERT (false);
1264  }
1265  NS_LOG_DEBUG ("GetTxopFragmentOffset returning " << offset);
1266  return offset;
1267 }
1268 
1269 uint32_t
1270 QosTxop::GetNextTxopFragmentSize (uint32_t fragmentNumber) const
1271 {
1272  NS_LOG_FUNCTION (this << fragmentNumber);
1273  uint32_t fragmentSize = GetTxopFragmentSize ();
1274  uint32_t nFragments = GetNTxopFragment ();
1275  if (fragmentNumber >= nFragments)
1276  {
1277  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning 0");
1278  return 0;
1279  }
1280  if (fragmentNumber == nFragments - 1)
1281  {
1282  fragmentSize = (m_currentPacket->GetSize () - ((nFragments - 1) * fragmentSize));
1283  }
1284  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning " << fragmentSize);
1285  return fragmentSize;
1286 }
1287 
1288 uint32_t
1290 {
1291  uint32_t size;
1292  if (IsTxopFragmentation ())
1293  {
1295  }
1296  else
1297  {
1299  }
1300  return size;
1301 }
1302 
1303 uint32_t
1305 {
1306  uint32_t size;
1307  if (IsTxopFragmentation ())
1308  {
1310  }
1311  else
1312  {
1314  }
1315  return size;
1316 }
1317 
1318 uint32_t
1320 {
1321  uint32_t offset;
1322  if (IsTxopFragmentation ())
1323  {
1325  }
1326  else
1327  {
1330  }
1331  return offset;
1332 }
1333 
1334 bool
1336 {
1337  bool isLastFragment;
1338  if (IsTxopFragmentation ())
1339  {
1340  isLastFragment = (m_fragmentNumber == GetNTxopFragment () - 1);
1341  }
1342  else
1343  {
1346  }
1347  return isLastFragment;
1348 }
1349 
1352 {
1353  NS_LOG_FUNCTION (this << hdr);
1354  *hdr = m_currentHdr;
1356  uint32_t startOffset = GetFragmentOffset ();
1357  Ptr<Packet> fragment;
1358  if (IsLastFragment ())
1359  {
1360  hdr->SetNoMoreFragments ();
1361  }
1362  else
1363  {
1364  hdr->SetMoreFragments ();
1365  }
1366  fragment = m_currentPacket->CreateFragment (startOffset,
1367  GetFragmentSize ());
1368  return fragment;
1369 }
1370 
1371 void
1373 {
1374  NS_LOG_FUNCTION (this << +ac);
1375  m_ac = ac;
1376 }
1377 
1380 {
1381  NS_LOG_FUNCTION (this << &hdr);
1382  Mac48Address retval;
1383  if (GetTypeOfStation () == STA || GetTypeOfStation () == ADHOC_STA)
1384  {
1385  retval = hdr.GetAddr2 ();
1386  }
1387  else
1388  {
1389  retval = hdr.GetAddr3 ();
1390  }
1391  return retval;
1392 }
1393 
1396 {
1397  NS_LOG_FUNCTION (this << &hdr);
1398  Mac48Address retval;
1399  if (GetTypeOfStation () == AP || GetTypeOfStation () == ADHOC_STA)
1400  {
1401  retval = hdr.GetAddr1 ();
1402  }
1403  else
1404  {
1405  retval = hdr.GetAddr3 ();
1406  }
1407  return retval;
1408 }
1409 
1410 void
1412 {
1413  NS_LOG_FUNCTION (this << packet << &hdr);
1414  WifiMacTrailer fcs;
1415  m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr, packet);
1416  m_queue->PushFront (Create<WifiMacQueueItem> (packet, hdr));
1418 }
1419 
1420 void
1422 {
1423  NS_LOG_FUNCTION (this << respHdr << recipient);
1424  uint8_t tid = respHdr->GetTid ();
1425  if (respHdr->GetStatusCode ().IsSuccess ())
1426  {
1427  NS_LOG_DEBUG ("block ack agreement established with " << recipient);
1428  m_baManager->UpdateAgreement (respHdr, recipient);
1429  }
1430  else
1431  {
1432  NS_LOG_DEBUG ("discard ADDBA response" << recipient);
1433  m_baManager->NotifyAgreementRejected (recipient, tid);
1434  }
1436 }
1437 
1438 void
1440 {
1441  NS_LOG_FUNCTION (this << delBaHdr << recipient);
1442  NS_LOG_DEBUG ("received DELBA frame from=" << recipient);
1443  m_baManager->DestroyAgreement (recipient, delBaHdr->GetTid ());
1444 }
1445 
1446 void
1447 QosTxop::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, WifiMode txMode, double dataSnr)
1448 {
1449  NS_LOG_FUNCTION (this << blockAck << recipient << rxSnr << txMode.GetUniqueName () << dataSnr);
1450  NS_LOG_DEBUG ("got block ack from=" << recipient);
1451  m_baManager->NotifyGotBlockAck (blockAck, recipient, rxSnr, txMode, dataSnr);
1452  if (!m_txOkCallback.IsNull ())
1453  {
1455  }
1456  m_currentPacket = 0;
1457  ResetCw ();
1458 }
1459 
1460 void
1462 {
1463  NS_LOG_FUNCTION (this);
1464  uint8_t tid = m_currentHdr.GetQosTid ();
1465  Mac48Address recipient = m_currentHdr.GetAddr1 ();
1466  Ptr<const WifiMacQueueItem> item = Create<const WifiMacQueueItem> (m_currentPacket, m_currentHdr);
1467  WifiModulationClass modulation = m_low->GetDataTxVector (item).GetMode ().GetModulationClass ();
1468  if ((m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED))
1469  && (GetLow ()->GetMpduAggregator () == 0 ||
1470  GetLow ()->GetMpduAggregator ()->GetMaxAmpduSize (m_currentHdr.GetAddr1 (), tid, modulation) == 0))
1471  {
1473  }
1474 }
1475 
1477 {
1478  NS_LOG_FUNCTION (this << dest);
1479  auto it = m_aMpduEnabled.find (dest);
1480  if (it != m_aMpduEnabled.end ())
1481  {
1482  return it->second;
1483  }
1484  return false;
1485 }
1486 
1487 void QosTxop::SetAmpduExist (Mac48Address dest, bool enableAmpdu)
1488 {
1489  NS_LOG_FUNCTION (this << dest << enableAmpdu);
1490  m_aMpduEnabled[dest] = enableAmpdu;
1491 }
1492 
1493 void
1495 {
1496  NS_LOG_FUNCTION (this);
1498  {
1499  if (!m_currentHdr.IsRetry ())
1500  {
1501  m_baManager->StorePacket (Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr,
1503  }
1504  m_baManager->NotifyMpduTransmission (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid (),
1505  m_txMiddle->GetNextSeqNumberByTidAndAddress (m_currentHdr.GetQosTid (),
1507  }
1508 }
1509 
1510 void
1512 {
1513  NS_ASSERT (mpdu->GetHeader ().IsQosData ());
1514  m_baManager->StorePacket (mpdu);
1515  m_baManager->NotifyMpduTransmission (mpdu->GetHeader ().GetAddr1 (), mpdu->GetHeader ().GetQosTid (),
1516  m_txMiddle->GetNextSeqNumberByTidAndAddress (mpdu->GetHeader ().GetQosTid (),
1517  mpdu->GetHeader ().GetAddr1 ()),
1519 }
1520 
1521 bool
1523 {
1524  NS_LOG_FUNCTION (this);
1525  uint8_t tid = m_currentHdr.GetQosTid ();
1526  Mac48Address recipient = m_currentHdr.GetAddr1 ();
1527  uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, recipient);
1528  if ((GetBlockAckThreshold () > 0 && packets >= GetBlockAckThreshold ())
1529  || (GetLow ()->GetMpduAggregator () != 0 && GetLow ()->GetMpduAggregator ()->GetMaxAmpduSize (recipient, tid, WIFI_MOD_CLASS_HT) > 0 && packets > 1)
1532  {
1533  /* Block ack setup */
1534  uint16_t startingSequence = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
1535  SendAddBaRequest (recipient, tid, startingSequence, m_blockAckInactivityTimeout, true);
1536  return true;
1537  }
1538  return false;
1539 }
1540 
1541 void
1543 {
1544  NS_LOG_FUNCTION (this << &bar);
1545  WifiMacHeader hdr;
1547  hdr.SetAddr1 (bar.recipient);
1548  hdr.SetAddr2 (m_low->GetAddress ());
1549  hdr.SetDsNotTo ();
1550  hdr.SetDsNotFrom ();
1551  hdr.SetNoRetry ();
1552  hdr.SetNoMoreFragments ();
1553 
1554  m_currentPacket = bar.bar;
1555  m_currentHdr = hdr;
1556 
1557  Ptr<WifiMacQueueItem> mpdu = Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr);
1559 
1560  m_low->StartTransmission (mpdu, m_currentParams, this);
1561 }
1562 
1563 void
1565 {
1566  NS_LOG_FUNCTION (this);
1567  m_baManager->SetTxMiddle (m_txMiddle);
1568  m_low->RegisterEdcaForAc (m_ac, this);
1569  m_baManager->SetBlockAckInactivityCallback (MakeCallback (&QosTxop::SendDelbaFrame, this));
1570 }
1571 
1572 void
1574 {
1575  NS_LOG_FUNCTION (this << +threshold);
1576  m_blockAckThreshold = threshold;
1577  m_baManager->SetBlockAckThreshold (threshold);
1578 }
1579 
1580 void
1582 {
1583  NS_LOG_FUNCTION (this << timeout);
1585 }
1586 
1587 uint8_t
1589 {
1590  NS_LOG_FUNCTION (this);
1591  return m_blockAckThreshold;
1592 }
1593 
1594 void
1595 QosTxop::SendAddBaRequest (Mac48Address dest, uint8_t tid, uint16_t startSeq,
1596  uint16_t timeout, bool immediateBAck)
1597 {
1598  NS_LOG_FUNCTION (this << dest << +tid << startSeq << timeout << immediateBAck);
1599  NS_LOG_DEBUG ("sent ADDBA request to " << dest);
1600  WifiMacHeader hdr;
1602  hdr.SetAddr1 (dest);
1603  hdr.SetAddr2 (m_low->GetAddress ());
1604  hdr.SetAddr3 (m_low->GetBssid ());
1605  hdr.SetDsNotTo ();
1606  hdr.SetDsNotFrom ();
1607 
1608  WifiActionHeader actionHdr;
1611  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1612 
1613  Ptr<Packet> packet = Create<Packet> ();
1614  /*Setting ADDBARequest header*/
1615  MgtAddBaRequestHeader reqHdr;
1616  reqHdr.SetAmsduSupport (true);
1617  if (immediateBAck)
1618  {
1619  reqHdr.SetImmediateBlockAck ();
1620  }
1621  else
1622  {
1623  reqHdr.SetDelayedBlockAck ();
1624  }
1625  reqHdr.SetTid (tid);
1626  /* For now we don't use buffer size field in the ADDBA request frame. The recipient
1627  * will choose how many packets it can receive under block ack.
1628  */
1629  reqHdr.SetBufferSize (0);
1630  reqHdr.SetTimeout (timeout);
1631  reqHdr.SetStartingSequence (startSeq);
1632 
1633  m_baManager->CreateAgreement (&reqHdr, dest);
1634 
1635  packet->AddHeader (reqHdr);
1636  packet->AddHeader (actionHdr);
1637 
1638  m_currentPacket = packet;
1639  m_currentHdr = hdr;
1640 
1641  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
1642  m_currentHdr.SetSequenceNumber (sequence);
1647 
1651 
1652  m_low->StartTransmission (Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr), m_currentParams, this);
1653 }
1654 
1655 void
1656 QosTxop::SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator)
1657 {
1658  NS_LOG_FUNCTION (this << addr << +tid << byOriginator);
1659  WifiMacHeader hdr;
1661  hdr.SetAddr1 (addr);
1662  hdr.SetAddr2 (m_low->GetAddress ());
1663  hdr.SetAddr3 (m_low->GetBssid ());
1664  hdr.SetDsNotTo ();
1665  hdr.SetDsNotFrom ();
1666 
1667  MgtDelBaHeader delbaHdr;
1668  delbaHdr.SetTid (tid);
1669  if (byOriginator)
1670  {
1671  delbaHdr.SetByOriginator ();
1672  m_baManager->DestroyAgreement (addr, tid);
1673  }
1674  else
1675  {
1676  delbaHdr.SetByRecipient ();
1677  m_low->DestroyBlockAckAgreement (addr, tid);
1678  }
1679 
1680  WifiActionHeader actionHdr;
1683  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1684 
1685  Ptr<Packet> packet = Create<Packet> ();
1686  packet->AddHeader (delbaHdr);
1687  packet->AddHeader (actionHdr);
1688 
1689  PushFront (packet, hdr);
1690 }
1691 
1692 void
1694 {
1695  NS_LOG_FUNCTION (this);
1696  ResetCw ();
1697  m_cwTrace = GetCw ();
1698  m_backoff = m_rng->GetInteger (0, GetCw ());
1701 }
1702 
1703 void
1705 {
1706  NS_LOG_FUNCTION (this << hdr);
1707  if (!m_txOkCallback.IsNull ())
1708  {
1710  }
1711 }
1712 
1713 void
1715 {
1716  NS_LOG_FUNCTION (this << hdr);
1717  if (!m_txFailedCallback.IsNull ())
1718  {
1720  }
1721 }
1722 
1723 void
1725 {
1726  NS_LOG_FUNCTION (this << recipient << +tid);
1727  // If agreement is still pending, ADDBA response is not received
1728  if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::PENDING))
1729  {
1730  m_baManager->NotifyAgreementNoReply (recipient, tid);
1731  Simulator::Schedule (m_failedAddBaTimeout, &QosTxop::ResetBa, this, recipient, tid);
1732  m_backoff = m_rng->GetInteger (0, GetCw ());
1736  }
1737 }
1738 
1739 void
1740 QosTxop::ResetBa (Mac48Address recipient, uint8_t tid)
1741 {
1742  NS_LOG_FUNCTION (this << recipient << +tid);
1743  // This function is scheduled when waiting for an ADDBA response. However,
1744  // before this function is called, a DELBA request may arrive, which causes
1745  // the agreement to be deleted. Hence, check if an agreement exists before
1746  // notifying that the agreement has to be reset.
1747  if (m_baManager->ExistsAgreement (recipient, tid)
1748  && !m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED))
1749  {
1750  m_baManager->NotifyAgreementReset (recipient, tid);
1751  }
1752 }
1753 
1754 void
1756 {
1757  NS_LOG_FUNCTION (this << addBaResponseTimeout);
1758  m_addBaResponseTimeout = addBaResponseTimeout;
1759 }
1760 
1761 Time
1763 {
1764  return m_addBaResponseTimeout;
1765 }
1766 
1767 void
1769 {
1770  NS_LOG_FUNCTION (this << failedAddBaTimeout);
1771  m_failedAddBaTimeout = failedAddBaTimeout;
1772 }
1773 
1774 Time
1776 {
1777  return m_failedAddBaTimeout;
1778 }
1779 
1780 bool
1782 {
1783  return true;
1784 }
1785 
1786 } //namespace ns3
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
AcIndex m_ac
the access category
Definition: qos-txop.h:602
TxFailed m_txFailedCallback
the transmit failed callback
Definition: txop.h:502
bool IsRetry(void) const
Return if the Retry bit is set.
void SetRetry(void)
Set the Retry bit in the Frame Control field.
bool IsSuccess(void) const
Return whether the status code is success.
Definition: status-code.cc:42
void MissedAck(void)
Event handler when an ACK is missed.
Definition: qos-txop.cc:793
Ptr< const WifiMacQueueItem > PeekNextFrame(uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast())
Peek the next frame to transmit to the given receiver and of the given TID from the Block Ack manager...
Definition: qos-txop.cc:202
void SetMoreFragments(void)
Set the More Fragment bit in the Frame Control field.
bool IsBroadcast(void) const
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
Time GetTxopRemaining(void) const
Return the remaining duration in the current TXOP.
Definition: qos-txop.cc:1134
bool GetVhtSupported(void) const
Return whether the device has VHT capability support enabled.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
bool GetAmpduExist(Mac48Address dest) const
Return whether A-MPDU is used to transmit data to a peer station.
Definition: qos-txop.cc:1476
Ptr< MacTxMiddle > m_txMiddle
the MacTxMiddle
Definition: txop.h:505
void ResetBa(Mac48Address recipient, uint8_t tid)
Reset BA agreement after BA negotiation failed.
Definition: qos-txop.cc:1740
void VerifyBlockAck(void)
Verifies if dequeued packet has to be transmitted with ack policy Block Ack.
Definition: qos-txop.cc:1461
AttributeValue implementation for Boolean.
Definition: boolean.h:36
void RestartAccessIfNeeded(void)
Restart access request if needed.
Definition: qos-txop.cc:940
TracedCallback< uint32_t > m_backoffTrace
backoff trace value
Definition: txop.h:530
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
TracedValue< uint32_t > m_cwTrace
CW trace value.
Definition: txop.h:531
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
BlockAckType m_blockAckType
the Block ACK type
Definition: qos-txop.h:607
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
void ReportFinalDataFailed(Mac48Address address, const WifiMacHeader *header, uint32_t packetSize)
Should be invoked after calling ReportDataFailed if NeedRetransmission returns false.
Time m_startTxop
the start TXOP time
Definition: qos-txop.h:611
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
Definition: mgt-headers.h:864
Mac48Address MapDestAddressForAggregation(const WifiMacHeader &hdr)
This functions are used only to correctly set destination address in A-MSDU subframes.
Definition: qos-txop.cc:1395
void EnableBasicBlockAck(void)
Wait BASICBLOCKACKTimeout for a Basic Block Ack Response frame.
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:84
uint32_t m_backoff
the current backoff
Definition: txop.h:513
bool m_isAccessRequestedForRts
flag whether access is requested to transmit a RTS frame
Definition: qos-txop.h:612
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:91
void MissedBlockAck(uint8_t nMpdus)
Event handler when a Block ACK timeout has occurred.
Definition: qos-txop.cc:853
Implement the header for management frames of type add block ack request.
Definition: mgt-headers.h:997
bool NeedBarRetransmission(void)
Check if Block ACK Request should be re-transmitted.
Definition: qos-txop.cc:1012
void SetNoMoreFragments(void)
Un-set the More Fragment bit in the Frame Control Field.
Ptr< ChannelAccessManager > m_channelAccessManager
the channel access manager
Definition: txop.h:500
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
bool GetHeSupported(void) const
Return whether the device has HE capability support enabled.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:204
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1070
Ptr< WifiMacQueueItem > DequeuePeekedFrame(Ptr< const WifiMacQueueItem > peekedItem, WifiTxVector txVector, bool aggregate=true, uint32_t ampduSize=0, Time ppduDurationLimit=Seconds(0))
Dequeue the frame that has been previously peeked by calling PeekNextFrame or PeekNextFrameByTidAndAd...
Definition: qos-txop.cc:267
void SetBlockAckInactivityTimeout(uint16_t timeout)
Set the Block Ack inactivity timeout.
Definition: qos-txop.cc:1581
void SendDelbaFrame(Mac48Address addr, uint8_t tid, bool byOriginator)
Sends DELBA frame to cancel a block ack agreement with sta addressed by addr for tid tid...
Definition: qos-txop.cc:1656
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
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:84
bool IsStrictlyPositive(void) const
Definition: nstime.h:308
uint16_t GetBaStartingSequence(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:137
bool NeedRts(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, WifiTxVector txVector)
void GotDelBaFrame(const MgtDelBaHeader *delBaHdr, Mac48Address recipient)
Event handler when a DELBA frame is received.
Definition: qos-txop.cc:1439
void UpdateFragmentationThreshold(void)
Typically called to update the fragmentation threshold at the start of a new transmission.
WifiMacType GetType(void) const
Return the type (enum WifiMacType)
bool IsLastFragment(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, uint32_t fragmentNumber)
Ptr< UniformRandomVariable > m_rng
the random stream
Definition: txop.h:508
CategoryValue GetCategory()
Return the category value.
virtual ~QosTxop()
Definition: qos-txop.cc:110
void PrepareForQueue(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
ns3::Time timeout
void SetAccessCategory(AcIndex ac)
Set the access category of this EDCAF.
Definition: qos-txop.cc:1372
static TypeId GetTypeId(void)
Get the type ID.
Definition: qos-txop.cc:52
uint8_t GetBlockAckThreshold(void) const
Return the current threshold for block ACK mechanism.
Definition: qos-txop.cc:1588
Block Ack Request.
void DoDispose(void)
Destructor implementation.
Definition: qos-txop.cc:116
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
uint32_t GetTxopFragmentSize(void) const
Calculate the size of the current TXOP fragment.
Definition: qos-txop.cc:1198
Time m_failedAddBaTimeout
timeout after failed BA agreement
Definition: qos-txop.h:615
control how a packet is transmitted.
void SetAmsduSupport(bool supported)
Enable or disable A-MSDU support.
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
bool IsBlockAck(void) const
Return true if the header is a Block ACK header.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
bool IsLastFragment(void) const
Check if the current fragment is the last fragment.
Definition: qos-txop.cc:1335
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:446
uint8_t GetTid(void) const
Return the Traffic ID (TID).
bool IsBlockAckReq(void) const
Return true if the header is a Block ACK Request header.
uint32_t GetFragmentOffset(void) const
Calculate the offset for the current fragment.
Definition: qos-txop.cc:1319
bool IsByOriginator(void) const
Check if the initiator bit in the DELBA is set.
void UpdateFailedCw(void)
Update the value of the CW variable to take into account a transmission failure.
Definition: txop.cc:224
Time GetAddBaResponseTimeout(void) const
Get the timeout for ADDBA response.
Definition: qos-txop.cc:1762
virtual uint32_t GetInteger(void)=0
Get the next random value as an integer drawn from the distribution.
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:220
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1389
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
bool IsZero(void) const
Definition: nstime.h:288
AttributeValue implementation for Time.
Definition: nstime.h:1124
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
bool IsQosAmsdu(void) const
Check if the A-MSDU present bit is set in the QoS control field.
void ReportRtsFailed(Mac48Address address, const WifiMacHeader *header)
Should be invoked whenever the RtsTimeout associated to a transmission attempt expires.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
uint32_t GetNextFragmentSize(void) const
Calculate the size of the next fragment.
Definition: qos-txop.cc:1304
void SetAmpduExist(Mac48Address dest, bool enableAmpdu)
Set indication whether A-MPDU is used to transmit data to a peer station.
Definition: qos-txop.cc:1487
void StartAccessIfNeeded(void)
Request access from DCF manager if needed.
Definition: qos-txop.cc:980
void EnableExtendedCompressedBlockAck(void)
Wait COMPRESSEDBLOCKACKTimeout for an Extended Compressed Block Ack Response frame.
void SetFailedAddBaTimeout(Time failedAddBaTimeout)
Set the timeout for failed BA agreement.
Definition: qos-txop.cc:1768
void SendBlockAckRequest(const Bar &bar)
After that all packets, for which a block ack agreement was established, have been transmitted...
Definition: qos-txop.cc:1542
bool GetHtSupported(void) const
Return whether the device has HT capability support enabled.
Ptr< BlockAckManager > m_baManager
the Block ACK manager
Definition: qos-txop.h:605
Mac48Address GetAddr3(void) const
Return the address in the Address 3 field.
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
HT PHY (Clause 20)
Definition: wifi-mode.h:58
static Mac48Address GetBroadcast(void)
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
Headers for Block ack response.
Definition: ctrl-headers.h:193
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
void GotAddBaResponse(const MgtAddBaResponseHeader *respHdr, Mac48Address recipient)
Event handler when an ADDBA response is received.
Definition: qos-txop.cc:1421
void SetTypeOfStation(TypeOfStation type)
Set type of station with the given type.
Definition: qos-txop.cc:151
static const ConstIterator EMPTY
Invalid iterator to signal an empty queue.
virtual bool IsAccessRequested(void) const
Definition: txop.cc:454
bool GetQosSupported(Mac48Address address) const
Return whether the given station is QoS capable.
std::string GetUniqueName(void) const
Definition: wifi-mode.cc:457
#define list
uint32_t GetFragmentSize(void) const
Calculate the size of the current fragment.
Definition: qos-txop.cc:1289
uint16_t GetNextSequenceNumberFor(const WifiMacHeader *hdr)
Return the next sequence number for the given header.
Definition: qos-txop.cc:164
void PushFront(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Definition: qos-txop.cc:1411
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:170
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
bool IsQosTxop(void) const
Check for QoS TXOP.
Definition: qos-txop.cc:1781
uint32_t GetNTxopFragment(void) const
Calculate the number of TXOP fragments needed for the transmission of the current packet...
Definition: qos-txop.cc:1231
Mac48Address recipient
recipient
void SetAddBaResponseTimeout(Time addBaResponseTimeout)
Set the timeout to wait for ADDBA response.
Definition: qos-txop.cc:1755
void SetByOriginator(void)
Set the initiator bit in the DELBA.
uint32_t GetFragmentOffset(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, uint32_t fragmentNumber)
void SetByRecipient(void)
Un-set the initiator bit in the DELBA.
bool NeedRtsRetransmission(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Check if RTS should be re-transmitted if CTS was missed.
Definition: txop.cc:372
void SetNoRetry(void)
Un-set the Retry bit in the Frame Control field.
Ptr< MacLow > GetLow(void) const
Return the MacLow associated with this Txop.
Definition: txop.cc:355
void EnableCompressedBlockAck(void)
Wait COMPRESSEDBLOCKACKTimeout for a Compressed Block Ack Response frame.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t GetCw(void) const
Definition: txop.cc:211
Hold objects of type Ptr<T>.
Definition: pointer.h:36
bool IsData(void) const
Return true if the Type is DATA.
address
Definition: first.py:37
StatusCode GetStatusCode(void) const
Return the status code.
void EnableAck(void)
Wait ACKTimeout for an ACK.
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void BaTxFailed(const WifiMacHeader &hdr)
The packet we sent was successfully received by the receiver.
Definition: qos-txop.cc:1714
Bar m_currentBar
the current BAR
Definition: qos-txop.h:610
uint32_t GetFragmentSize(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, uint32_t fragmentNumber)
void NotifyMissedCts(std::list< Ptr< WifiMacQueueItem >> mpduList)
Event handler when a CTS timeout has occurred.
Definition: qos-txop.cc:685
void CompleteMpduTx(Ptr< WifiMacQueueItem > mpdu)
Stores an MPDU (part of an A-MPDU) in blockackagreement (i.e.
Definition: qos-txop.cc:1511
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
Ptr< WifiMacQueue > m_queue
the wifi MAC queue
Definition: txop.h:504
virtual void DoDispose(void)
Destructor implementation.
Definition: txop.cc:107
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:215
an EUI-48 address
Definition: mac48-address.h:43
MacLowTransmissionParameters GetTransmissionParameters(Ptr< const WifiMacQueueItem > frame) const
Compute the MacLow transmission parameters for the given frame.
Definition: qos-txop.cc:366
bool NeedDataRetransmission(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Check if DATA should be re-transmitted if ACK was missed.
Definition: txop.cc:379
void BaTxOk(const WifiMacHeader &hdr)
The packet we sent was successfully received by the receiver.
Definition: qos-txop.cc:1704
Ptr< const Packet > m_currentPacket
the current packet
Definition: txop.h:526
uint8_t GetTid(Ptr< const Packet > packet, const WifiMacHeader hdr)
Extraction operator for TypeId.
Definition: qos-utils.cc:99
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:1125
void SetTid(uint8_t tid)
Set Traffic ID (TID).
void EndTxNoAck(void)
Event handler when a transmission that does not require an ACK has completed.
Definition: qos-txop.cc:1147
bool IsGroup(void) const
void DisableRts(void)
Do not send rts and wait for cts before sending data.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:193
void SetBlockAckThreshold(uint8_t threshold)
Set threshold for block ACK mechanism.
Definition: qos-txop.cc:1573
Ptr< MacLow > m_low
the MacLow
Definition: txop.h:506
uint8_t m_blockAckThreshold
the Block ACK threshold
Definition: qos-txop.h:606
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > remoteManager)
Set WifiRemoteStationsManager this QosTxop is associated to.
Definition: qos-txop.cc:143
uint32_t GetTxopFragmentOffset(uint32_t fragmentNumber) const
Calculate the offset for the fragment.
Definition: qos-txop.cc:1244
void NotifyCollision(void)
Notify the EDCAF that collision has occurred.
Definition: qos-txop.cc:675
uint8_t GetTid(void) const
Return the Traffic ID (TID).
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
bool IsQosBlockAck(void) const
Return if the QoS ACK policy is Block ACK.
bool IsQosOldPacket(Ptr< const WifiMacQueueItem > mpdu)
Check if the given MPDU is to be considered old according to the current starting sequence number of ...
Definition: qos-txop.cc:176
void ReportDataFailed(Mac48Address address, const WifiMacHeader *header, uint32_t packetSize)
Should be invoked whenever the AckTimeout associated to a transmission attempt expires.
MacLowTransmissionParameters m_currentParams
current transmission parameters
Definition: txop.h:528
void GotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, WifiMode txMode, double dataSnr)
Event handler when a Block ACK is received.
Definition: qos-txop.cc:1447
WifiModulationClass
This enumeration defines the modulation classes per (Table 9-4 "Modulation classes"; IEEE 802...
Definition: wifi-mode.h:36
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
void GotAck(void)
Event handler when an ACK is received.
Definition: qos-txop.cc:733
void StartNextPacket(void)
Start transmission for the next packet if allowed by the TxopLimit.
Definition: qos-txop.cc:1035
void EnableRts(void)
Send a RTS, and wait CTSTimeout for a CTS.
bool m_accessRequested
flag whether channel access is already requested
Definition: txop.h:514
BlockAckActionValue blockAck
block ack
Definition: mgt-headers.h:940
void Unblock(Mac48Address dest, uint8_t tid)
Un-block the given destination address and TID (e.g.
bool IsPositive(void) const
Definition: nstime.h:298
void CompleteTx(void)
For now is typically invoked to complete transmission of a packets sent with ack policy Block Ack: th...
Definition: qos-txop.cc:1494
Implement the header for management frames of type add block ack response.
Definition: mgt-headers.h:1129
bool IsStrictlyNegative(void) const
Definition: nstime.h:303
Implement the header for management frames of type del block ack.
Definition: mgt-headers.h:1250
Mac48Address MapSrcAddressForAggregation(const WifiMacHeader &hdr)
This functions are used only to correctly set source address in A-MSDU subframes. ...
Definition: qos-txop.cc:1379
bool GetBaAgreementEstablished(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:125
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:272
bool m_useExplicitBarAfterMissedBlockAck
flag whether explicit Block Ack Request should be sent upon missed Block Ack Response ...
Definition: qos-txop.h:616
TypeOfStation GetTypeOfStation(void) const
Return type of station.
Definition: qos-txop.cc:158
typedef for union of different ActionValues
Definition: mgt-headers.h:935
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1062
Ptr< const Packet > bar
block ack request
Ptr< QosBlockedDestinations > m_qosBlockedDestinations
QOS blocked destinations.
Definition: qos-txop.h:604
void NotifyAccessGranted(void)
Notify the EDCAF that access has been granted.
Definition: qos-txop.cc:460
uint16_t GetBaBufferSize(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:131
bool NeedFragmentation(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
void Block(Mac48Address dest, uint8_t tid)
Block the given destination address and TID from sending (e.g.
TxOk m_txOkCallback
the transmit OK callback
Definition: txop.h:501
void DisableNextData(void)
Do not attempt to send data burst after current transmission.
virtual void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > remoteManager)
Set WifiRemoteStationsManager this Txop is associated to.
Definition: txop.cc:140
void CompleteConfig(void)
Complete block ACK configuration.
Definition: qos-txop.cc:1564
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS DATA...
bool m_currentIsFragmented
flag whether current packet is fragmented
Definition: qos-txop.h:613
bool IsAction() const
Return true if the header is an Action header.
uint8_t m_fragmentNumber
the fragment number
Definition: txop.h:529
TracedCallback< Time, Time > m_txopTrace
TXOP trace callback.
Definition: qos-txop.h:618
void DoInitialize(void)
Initialize() implementation.
Definition: qos-txop.cc:1693
void ReportAmpduTxStatus(Mac48Address address, uint8_t tid, uint8_t nSuccessfulMpdus, uint8_t nFailedMpdus, double rxSnr, double dataSnr)
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
uint8_t GetTid(void) const
Return the Traffic ID (TID).
void TerminateTxop(void)
Update backoff and restart access if needed.
Definition: qos-txop.cc:1118
bool NeedFragmentation(void) const
Check if the current packet should be fragmented.
Definition: qos-txop.cc:1157
TypeOfStation
Enumeration for type of station.
Definition: qos-txop.h:46
WifiMacHeader m_currentHdr
the current header
Definition: txop.h:527
Time m_currentPacketTimestamp
the current packet timestamp
Definition: qos-txop.h:608
bool IsTxopFragmentation(void) const
Check if the current packet is fragmented because of an exceeded TXOP duration.
Definition: qos-txop.cc:1183
Ptr< Packet > GetFragmentPacket(WifiMacHeader *hdr)
Get the next fragment from the packet with appropriate Wifi header for the fragment.
Definition: qos-txop.cc:1351
Time GetFailedAddBaTimeout(void) const
Get the timeout for failed BA agreement.
Definition: qos-txop.cc:1775
ActionValue GetAction()
Return the action value.
uint16_t m_blockAckInactivityTimeout
the Block ACK inactivity timeout
Definition: qos-txop.h:609
Headers for Block ack request.
Definition: ctrl-headers.h:41
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1270
Ptr< WifiRemoteStationManager > m_stationManager
the wifi remote station manager
Definition: txop.h:507
bool SetupBlockAckIfNeeded(void)
If number of packets in the queue reaches m_blockAckThreshold value, an ADDBA Request frame is sent t...
Definition: qos-txop.cc:1522
void SetFragmentNumber(uint8_t frag)
Set the fragment number of the header.
void DisableAck(void)
Do not wait for Ack after data transmission.
void NotifyInternalCollision(void)
Notify the EDCAF that internal collision has occurred.
Definition: qos-txop.cc:591
void ResetCw(void)
Update the value of the CW variable to take into account a transmission success or a transmission abo...
Definition: txop.cc:217
uint32_t GetNextTxopFragmentSize(uint32_t fragmentNumber) const
Calculate the size of the next TXOP fragment.
Definition: qos-txop.cc:1270
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
TypeOfStation m_typeOfStation
the type of station
Definition: qos-txop.h:603
a unique identifier for an interface.
Definition: type-id.h:58
void ReportFinalRtsFailed(Mac48Address address, const WifiMacHeader *header)
Should be invoked after calling ReportRtsFailed if NeedRetransmission returns false.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:915
void StartBackoffNow(uint32_t nSlots)
Definition: txop.cc:253
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:38
void AddBaResponseTimeout(Mac48Address recipient, uint8_t tid)
Callback when ADDBA response is not received after timeout.
Definition: qos-txop.cc:1724
void RequestAccess(Ptr< Txop > state, bool isCfPeriod=false)
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
Implements the IEEE 802.11 MAC header.
Time m_addBaResponseTimeout
timeout for ADDBA response
Definition: qos-txop.h:614
std::map< Mac48Address, bool > m_aMpduEnabled
list containing flags whether A-MPDU is enabled for a given destination address
Definition: qos-txop.h:99
Implements the IEEE 802.11 MAC trailer.
void SendAddBaRequest(Mac48Address recipient, uint8_t tid, uint16_t startSeq, uint16_t timeout, bool immediateBAck)
Sends an ADDBA Request to establish a block ack agreement with sta addressed by recipient for tid tid...
Definition: qos-txop.cc:1595
void SetDsNotFrom(void)
Un-set the From DS bit in the Frame Control field.
Handle packet fragmentation and retransmissions for data and management frames.
Definition: txop.h:65
Time GetTxopLimit(void) const
Return the TXOP limit.
Definition: txop.cc:302
void SetQosAckPolicy(QosAckPolicy policy)
Set the QoS ACK policy in the QoS control field.