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  || !m_queue->IsEmpty () || m_baManager->HasPackets ())
945  && !IsAccessRequested ())
946  {
947  Ptr<const Packet> packet;
948  WifiMacHeader hdr;
949  if (m_currentPacket != 0)
950  {
951  packet = m_currentPacket;
952  hdr = m_currentHdr;
953  }
954  else
955  {
957  if (item)
958  {
959  packet = item->GetPacket ();
960  hdr = item->GetHeader ();
961  }
962  }
963  if (packet != 0)
964  {
966  m_low->GetDataTxVector (Create<const WifiMacQueueItem> (packet, hdr)));
967  }
968  else
969  {
971  }
973  }
974 }
975 
976 void
978 {
979  NS_LOG_FUNCTION (this);
980  if (m_currentPacket == 0
981  && (!m_queue->IsEmpty () || m_baManager->HasPackets ())
982  && !IsAccessRequested ())
983  {
984  Ptr<const Packet> packet;
985  WifiMacHeader hdr;
987  if (item)
988  {
989  packet = item->GetPacket ();
990  hdr = item->GetHeader ();
991  }
992  if (packet != 0)
993  {
995  m_low->GetDataTxVector (Create<const WifiMacQueueItem> (packet, hdr)));
996  }
997  else
998  {
1000  }
1002  }
1003 }
1004 
1005 bool
1007 {
1008  uint8_t tid = 0;
1009  uint16_t seqNumber = 0;
1010  if (m_currentHdr.IsQosData ())
1011  {
1012  tid = m_currentHdr.GetQosTid ();
1013  seqNumber = m_currentHdr.GetSequenceNumber ();
1014  }
1015  else if (m_currentHdr.IsBlockAckReq ())
1016  {
1017  CtrlBAckRequestHeader baReqHdr;
1018  m_currentPacket->PeekHeader (baReqHdr);
1019  tid = baReqHdr.GetTidInfo ();
1020  seqNumber = baReqHdr.GetStartingSequence ();
1021  }
1022  else if (m_currentHdr.IsBlockAck ())
1023  {
1024  CtrlBAckResponseHeader baRespHdr;
1025  m_currentPacket->PeekHeader (baRespHdr);
1026  tid = baRespHdr.GetTidInfo ();
1027  seqNumber = m_currentHdr.GetSequenceNumber ();
1028  }
1029  return m_baManager->NeedBarRetransmission (tid, seqNumber, m_currentHdr.GetAddr1 ());
1030 }
1031 
1032 void
1034 {
1035  NS_LOG_FUNCTION (this);
1036  NS_ASSERT (GetTxopLimit ().IsStrictlyPositive () && GetTxopRemaining ().IsStrictlyPositive ());
1037 
1038  m_currentPacket = 0;
1039  Ptr<const WifiMacQueueItem> nextFrame;
1040 
1041  // peek the next BlockAckReq, if any
1042  if (m_baManager->HasBar (m_currentBar, false))
1043  {
1044  WifiMacHeader hdr;
1047  nextFrame = Create<const WifiMacQueueItem> (m_currentBar.bar, hdr);
1048  }
1049  else
1050  {
1051  nextFrame = PeekNextFrame ();
1052  }
1053 
1054  if (nextFrame != 0)
1055  {
1057 
1058  if (GetTxopRemaining () >= m_low->CalculateOverallTxTime (nextFrame->GetPacket (), &nextFrame->GetHeader (), params))
1059  {
1060  if (nextFrame->GetHeader ().IsBlockAckReq ())
1061  {
1062  NS_LOG_DEBUG ("start next BlockAckReq within the current TXOP");
1063  m_baManager->HasBar (m_currentBar);
1065  return;
1066  }
1067 
1068  // check if a Block Ack agreement needs to be established
1069  m_currentHdr = nextFrame->GetHeader ();
1070  m_currentPacket = nextFrame->GetPacket ();
1073  && (!m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
1075  && SetupBlockAckIfNeeded ())
1076  {
1077  return;
1078  }
1079 
1080  // when dequeuing the peeked packet, A-MSDU aggregation is attempted if the
1081  // packet has been peeked from the EDCA queue. Thus, compute the max available
1082  // time for the transmission of the PPDU
1083  Time maxPpduDuration = GetTxopRemaining () - m_low->CalculateOverheadTxTime (nextFrame, params);
1084  NS_ASSERT (maxPpduDuration.IsPositive ());
1085 
1086  Ptr<WifiMacQueueItem> item = DequeuePeekedFrame (nextFrame, m_low->GetDataTxVector (nextFrame),
1087  true, 0, maxPpduDuration);
1088  NS_ASSERT (item != 0);
1089  NS_LOG_DEBUG ("start next packet " << *item << " within the current TXOP");
1090  m_currentPacket = item->GetPacket ();
1091  m_currentHdr = item->GetHeader ();
1092  m_currentPacketTimestamp = item->GetTimeStamp ();
1093  NS_ASSERT (m_currentPacket != 0);
1094 
1095  m_currentParams = params;
1097  m_fragmentNumber = 0;
1099  {
1100  VerifyBlockAck ();
1101  }
1102  GetLow ()->StartTransmission (item, m_currentParams, this);
1104  {
1105  CompleteTx ();
1106  }
1107  return;
1108  }
1109  }
1110 
1111  // terminate TXOP because no (suitable) frame was found
1112  TerminateTxop ();
1113 }
1114 
1115 void
1117 {
1118  NS_LOG_FUNCTION (this);
1119  if (GetTxopLimit ().IsStrictlyPositive ())
1120  {
1121  NS_LOG_DEBUG ("Terminating TXOP. Duration = " << Simulator::Now () - m_startTxop);
1123  }
1124  m_cwTrace = GetCw ();
1125  m_backoff = m_rng->GetInteger (0, GetCw ());
1129 }
1130 
1131 Time
1133 {
1134  Time remainingTxop = GetTxopLimit ();
1135  remainingTxop -= (Simulator::Now () - m_startTxop);
1136  if (remainingTxop.IsStrictlyNegative ())
1137  {
1138  remainingTxop = Seconds (0);
1139  }
1140  NS_LOG_FUNCTION (this << remainingTxop);
1141  return remainingTxop;
1142 }
1143 
1144 void
1146 {
1147  NS_LOG_FUNCTION (this);
1148  NS_LOG_DEBUG ("a transmission that did not require an ACK just finished");
1149  m_currentPacket = 0;
1150  ResetCw ();
1151  TerminateTxop ();
1152 }
1153 
1154 bool
1156 {
1157  NS_LOG_FUNCTION (this);
1162  && m_currentHdr.IsQosData ()
1164  && GetLow ()->GetMpduAggregator () != 0
1165  && GetLow ()->GetMpduAggregator ()->GetMaxAmpduSize (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr),
1167  {
1168  //MSDU is not fragmented when it is transmitted using an HT-immediate or
1169  //HT-delayed Block Ack agreement or when it is carried in an A-MPDU.
1170  return false;
1171  }
1172  bool needTxopFragmentation = false;
1174  {
1175  needTxopFragmentation = (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams) > GetTxopLimit ());
1176  }
1177  return (needTxopFragmentation || m_stationManager->NeedFragmentation (m_currentHdr.GetAddr1 (), &m_currentHdr, m_currentPacket));
1178 }
1179 
1180 bool
1182 {
1183  if (GetTxopLimit ().IsZero ())
1184  {
1185  return false;
1186  }
1189  {
1190  return true;
1191  }
1192  return false;
1193 }
1194 
1195 uint32_t
1197 {
1198  Time txopDuration = GetTxopLimit ();
1199  if (txopDuration.IsZero ())
1200  {
1201  return 0;
1202  }
1203  uint32_t maxSize = m_currentPacket->GetSize ();
1204  uint32_t minSize = 0;
1205  uint32_t size = 0;
1206  bool found = false;
1207  while (!found)
1208  {
1209  size = (minSize + ((maxSize - minSize) / 2));
1210  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) > txopDuration)
1211  {
1212  maxSize = size;
1213  }
1214  else
1215  {
1216  minSize = size;
1217  }
1218  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) <= txopDuration
1219  && GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size + 1) > txopDuration)
1220  {
1221  found = true;
1222  }
1223  }
1224  NS_ASSERT (size != 0);
1225  return size;
1226 }
1227 
1228 uint32_t
1230 {
1231  uint32_t fragmentSize = GetTxopFragmentSize ();
1232  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1233  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1234  {
1235  nFragments++;
1236  }
1237  NS_LOG_DEBUG ("GetNTxopFragment returning " << nFragments);
1238  return nFragments;
1239 }
1240 
1241 uint32_t
1242 QosTxop::GetTxopFragmentOffset (uint32_t fragmentNumber) const
1243 {
1244  if (fragmentNumber == 0)
1245  {
1246  return 0;
1247  }
1248  uint32_t offset = 0;
1249  uint32_t fragmentSize = GetTxopFragmentSize ();
1250  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1251  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1252  {
1253  nFragments++;
1254  }
1255  if (fragmentNumber < nFragments)
1256  {
1257  offset = (fragmentNumber * fragmentSize);
1258  }
1259  else
1260  {
1261  NS_ASSERT (false);
1262  }
1263  NS_LOG_DEBUG ("GetTxopFragmentOffset returning " << offset);
1264  return offset;
1265 }
1266 
1267 uint32_t
1268 QosTxop::GetNextTxopFragmentSize (uint32_t fragmentNumber) const
1269 {
1270  NS_LOG_FUNCTION (this << fragmentNumber);
1271  uint32_t fragmentSize = GetTxopFragmentSize ();
1272  uint32_t nFragments = GetNTxopFragment ();
1273  if (fragmentNumber >= nFragments)
1274  {
1275  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning 0");
1276  return 0;
1277  }
1278  if (fragmentNumber == nFragments - 1)
1279  {
1280  fragmentSize = (m_currentPacket->GetSize () - ((nFragments - 1) * fragmentSize));
1281  }
1282  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning " << fragmentSize);
1283  return fragmentSize;
1284 }
1285 
1286 uint32_t
1288 {
1289  uint32_t size;
1290  if (IsTxopFragmentation ())
1291  {
1293  }
1294  else
1295  {
1297  }
1298  return size;
1299 }
1300 
1301 uint32_t
1303 {
1304  uint32_t size;
1305  if (IsTxopFragmentation ())
1306  {
1308  }
1309  else
1310  {
1312  }
1313  return size;
1314 }
1315 
1316 uint32_t
1318 {
1319  uint32_t offset;
1320  if (IsTxopFragmentation ())
1321  {
1323  }
1324  else
1325  {
1328  }
1329  return offset;
1330 }
1331 
1332 bool
1334 {
1335  bool isLastFragment;
1336  if (IsTxopFragmentation ())
1337  {
1338  isLastFragment = (m_fragmentNumber == GetNTxopFragment () - 1);
1339  }
1340  else
1341  {
1344  }
1345  return isLastFragment;
1346 }
1347 
1350 {
1351  NS_LOG_FUNCTION (this << hdr);
1352  *hdr = m_currentHdr;
1354  uint32_t startOffset = GetFragmentOffset ();
1355  Ptr<Packet> fragment;
1356  if (IsLastFragment ())
1357  {
1358  hdr->SetNoMoreFragments ();
1359  }
1360  else
1361  {
1362  hdr->SetMoreFragments ();
1363  }
1364  fragment = m_currentPacket->CreateFragment (startOffset,
1365  GetFragmentSize ());
1366  return fragment;
1367 }
1368 
1369 void
1371 {
1372  NS_LOG_FUNCTION (this << +ac);
1373  m_ac = ac;
1374 }
1375 
1378 {
1379  NS_LOG_FUNCTION (this << &hdr);
1380  Mac48Address retval;
1381  if (GetTypeOfStation () == STA || GetTypeOfStation () == ADHOC_STA)
1382  {
1383  retval = hdr.GetAddr2 ();
1384  }
1385  else
1386  {
1387  retval = hdr.GetAddr3 ();
1388  }
1389  return retval;
1390 }
1391 
1394 {
1395  NS_LOG_FUNCTION (this << &hdr);
1396  Mac48Address retval;
1397  if (GetTypeOfStation () == AP || GetTypeOfStation () == ADHOC_STA)
1398  {
1399  retval = hdr.GetAddr1 ();
1400  }
1401  else
1402  {
1403  retval = hdr.GetAddr3 ();
1404  }
1405  return retval;
1406 }
1407 
1408 void
1410 {
1411  NS_LOG_FUNCTION (this << packet << &hdr);
1412  WifiMacTrailer fcs;
1413  m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr, packet);
1414  m_queue->PushFront (Create<WifiMacQueueItem> (packet, hdr));
1416 }
1417 
1418 void
1420 {
1421  NS_LOG_FUNCTION (this << respHdr << recipient);
1422  uint8_t tid = respHdr->GetTid ();
1423  if (respHdr->GetStatusCode ().IsSuccess ())
1424  {
1425  NS_LOG_DEBUG ("block ack agreement established with " << recipient);
1426  m_baManager->UpdateAgreement (respHdr, recipient);
1427  }
1428  else
1429  {
1430  NS_LOG_DEBUG ("discard ADDBA response" << recipient);
1431  m_baManager->NotifyAgreementRejected (recipient, tid);
1432  }
1434 }
1435 
1436 void
1438 {
1439  NS_LOG_FUNCTION (this << delBaHdr << recipient);
1440  NS_LOG_DEBUG ("received DELBA frame from=" << recipient);
1441  m_baManager->DestroyAgreement (recipient, delBaHdr->GetTid ());
1442 }
1443 
1444 void
1445 QosTxop::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, WifiMode txMode, double dataSnr)
1446 {
1447  NS_LOG_FUNCTION (this << blockAck << recipient << rxSnr << txMode.GetUniqueName () << dataSnr);
1448  NS_LOG_DEBUG ("got block ack from=" << recipient);
1449  m_baManager->NotifyGotBlockAck (blockAck, recipient, rxSnr, txMode, dataSnr);
1450  if (!m_txOkCallback.IsNull ())
1451  {
1453  }
1454  m_currentPacket = 0;
1455  ResetCw ();
1456 }
1457 
1458 void
1460 {
1461  NS_LOG_FUNCTION (this);
1462  uint8_t tid = m_currentHdr.GetQosTid ();
1463  Mac48Address recipient = m_currentHdr.GetAddr1 ();
1464  Ptr<const WifiMacQueueItem> item = Create<const WifiMacQueueItem> (m_currentPacket, m_currentHdr);
1465  WifiModulationClass modulation = m_low->GetDataTxVector (item).GetMode ().GetModulationClass ();
1466  if ((m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED))
1467  && (GetLow ()->GetMpduAggregator () == 0 ||
1468  GetLow ()->GetMpduAggregator ()->GetMaxAmpduSize (m_currentHdr.GetAddr1 (), tid, modulation) == 0))
1469  {
1471  }
1472 }
1473 
1475 {
1476  NS_LOG_FUNCTION (this << dest);
1477  auto it = m_aMpduEnabled.find (dest);
1478  if (it != m_aMpduEnabled.end ())
1479  {
1480  return it->second;
1481  }
1482  return false;
1483 }
1484 
1485 void QosTxop::SetAmpduExist (Mac48Address dest, bool enableAmpdu)
1486 {
1487  NS_LOG_FUNCTION (this << dest << enableAmpdu);
1488  m_aMpduEnabled[dest] = enableAmpdu;
1489 }
1490 
1491 void
1493 {
1494  NS_LOG_FUNCTION (this);
1496  {
1497  if (!m_currentHdr.IsRetry ())
1498  {
1499  m_baManager->StorePacket (Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr,
1501  }
1502  m_baManager->NotifyMpduTransmission (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid (),
1503  m_txMiddle->GetNextSeqNumberByTidAndAddress (m_currentHdr.GetQosTid (),
1505  }
1506 }
1507 
1508 void
1510 {
1511  NS_ASSERT (mpdu->GetHeader ().IsQosData ());
1512  m_baManager->StorePacket (mpdu);
1513  m_baManager->NotifyMpduTransmission (mpdu->GetHeader ().GetAddr1 (), mpdu->GetHeader ().GetQosTid (),
1514  m_txMiddle->GetNextSeqNumberByTidAndAddress (mpdu->GetHeader ().GetQosTid (),
1515  mpdu->GetHeader ().GetAddr1 ()),
1517 }
1518 
1519 bool
1521 {
1522  NS_LOG_FUNCTION (this);
1523  uint8_t tid = m_currentHdr.GetQosTid ();
1524  Mac48Address recipient = m_currentHdr.GetAddr1 ();
1525  uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, recipient);
1526  if ((GetBlockAckThreshold () > 0 && packets >= GetBlockAckThreshold ())
1527  || (GetLow ()->GetMpduAggregator () != 0 && GetLow ()->GetMpduAggregator ()->GetMaxAmpduSize (recipient, tid, WIFI_MOD_CLASS_HT) > 0 && packets > 1)
1530  {
1531  /* Block ack setup */
1532  uint16_t startingSequence = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
1533  SendAddBaRequest (recipient, tid, startingSequence, m_blockAckInactivityTimeout, true);
1534  return true;
1535  }
1536  return false;
1537 }
1538 
1539 void
1541 {
1542  NS_LOG_FUNCTION (this << &bar);
1543  WifiMacHeader hdr;
1545  hdr.SetAddr1 (bar.recipient);
1546  hdr.SetAddr2 (m_low->GetAddress ());
1547  hdr.SetAddr3 (m_low->GetBssid ());
1548  hdr.SetDsNotTo ();
1549  hdr.SetDsNotFrom ();
1550  hdr.SetNoRetry ();
1551  hdr.SetNoMoreFragments ();
1552 
1553  m_currentPacket = bar.bar;
1554  m_currentHdr = hdr;
1555 
1556  Ptr<WifiMacQueueItem> mpdu = Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr);
1558 
1559  m_low->StartTransmission (mpdu, m_currentParams, this);
1560 }
1561 
1562 void
1564 {
1565  NS_LOG_FUNCTION (this);
1566  m_baManager->SetTxMiddle (m_txMiddle);
1567  m_low->RegisterEdcaForAc (m_ac, this);
1568  m_baManager->SetBlockAckInactivityCallback (MakeCallback (&QosTxop::SendDelbaFrame, this));
1569 }
1570 
1571 void
1573 {
1574  NS_LOG_FUNCTION (this << +threshold);
1575  m_blockAckThreshold = threshold;
1576  m_baManager->SetBlockAckThreshold (threshold);
1577 }
1578 
1579 void
1581 {
1582  NS_LOG_FUNCTION (this << timeout);
1584 }
1585 
1586 uint8_t
1588 {
1589  NS_LOG_FUNCTION (this);
1590  return m_blockAckThreshold;
1591 }
1592 
1593 void
1594 QosTxop::SendAddBaRequest (Mac48Address dest, uint8_t tid, uint16_t startSeq,
1595  uint16_t timeout, bool immediateBAck)
1596 {
1597  NS_LOG_FUNCTION (this << dest << +tid << startSeq << timeout << immediateBAck);
1598  NS_LOG_DEBUG ("sent ADDBA request to " << dest);
1599  WifiMacHeader hdr;
1601  hdr.SetAddr1 (dest);
1602  hdr.SetAddr2 (m_low->GetAddress ());
1603  hdr.SetAddr3 (m_low->GetAddress ());
1604  hdr.SetDsNotTo ();
1605  hdr.SetDsNotFrom ();
1606 
1607  WifiActionHeader actionHdr;
1610  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1611 
1612  Ptr<Packet> packet = Create<Packet> ();
1613  /*Setting ADDBARequest header*/
1614  MgtAddBaRequestHeader reqHdr;
1615  reqHdr.SetAmsduSupport (true);
1616  if (immediateBAck)
1617  {
1618  reqHdr.SetImmediateBlockAck ();
1619  }
1620  else
1621  {
1622  reqHdr.SetDelayedBlockAck ();
1623  }
1624  reqHdr.SetTid (tid);
1625  /* For now we don't use buffer size field in the ADDBA request frame. The recipient
1626  * will choose how many packets it can receive under block ack.
1627  */
1628  reqHdr.SetBufferSize (0);
1629  reqHdr.SetTimeout (timeout);
1630  reqHdr.SetStartingSequence (startSeq);
1631 
1632  m_baManager->CreateAgreement (&reqHdr, dest);
1633 
1634  packet->AddHeader (reqHdr);
1635  packet->AddHeader (actionHdr);
1636 
1637  m_currentPacket = packet;
1638  m_currentHdr = hdr;
1639 
1640  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
1641  m_currentHdr.SetSequenceNumber (sequence);
1646 
1650 
1651  m_low->StartTransmission (Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr), m_currentParams, this);
1652 }
1653 
1654 void
1655 QosTxop::SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator)
1656 {
1657  NS_LOG_FUNCTION (this << addr << +tid << byOriginator);
1658  WifiMacHeader hdr;
1660  hdr.SetAddr1 (addr);
1661  hdr.SetAddr2 (m_low->GetAddress ());
1662  hdr.SetAddr3 (m_low->GetAddress ());
1663  hdr.SetDsNotTo ();
1664  hdr.SetDsNotFrom ();
1665 
1666  MgtDelBaHeader delbaHdr;
1667  delbaHdr.SetTid (tid);
1668  if (byOriginator)
1669  {
1670  delbaHdr.SetByOriginator ();
1671  m_baManager->DestroyAgreement (addr, tid);
1672  }
1673  else
1674  {
1675  delbaHdr.SetByRecipient ();
1676  m_low->DestroyBlockAckAgreement (addr, tid);
1677  }
1678 
1679  WifiActionHeader actionHdr;
1682  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1683 
1684  Ptr<Packet> packet = Create<Packet> ();
1685  packet->AddHeader (delbaHdr);
1686  packet->AddHeader (actionHdr);
1687 
1688  PushFront (packet, hdr);
1689 }
1690 
1691 void
1693 {
1694  NS_LOG_FUNCTION (this);
1695  ResetCw ();
1696  m_cwTrace = GetCw ();
1697  m_backoff = m_rng->GetInteger (0, GetCw ());
1700 }
1701 
1702 void
1704 {
1705  NS_LOG_FUNCTION (this << hdr);
1706  if (!m_txOkCallback.IsNull ())
1707  {
1709  }
1710 }
1711 
1712 void
1714 {
1715  NS_LOG_FUNCTION (this << hdr);
1716  if (!m_txFailedCallback.IsNull ())
1717  {
1719  }
1720 }
1721 
1722 void
1724 {
1725  NS_LOG_FUNCTION (this << recipient << +tid);
1726  // If agreement is still pending, ADDBA response is not received
1727  if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::PENDING))
1728  {
1729  m_baManager->NotifyAgreementNoReply (recipient, tid);
1730  Simulator::Schedule (m_failedAddBaTimeout, &QosTxop::ResetBa, this, recipient, tid);
1731  m_backoff = m_rng->GetInteger (0, GetCw ());
1735  }
1736 }
1737 
1738 void
1739 QosTxop::ResetBa (Mac48Address recipient, uint8_t tid)
1740 {
1741  NS_LOG_FUNCTION (this << recipient << +tid);
1742  if (!m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED))
1743  {
1744  m_baManager->NotifyAgreementReset (recipient, tid);
1745  }
1746 }
1747 
1748 void
1750 {
1751  NS_LOG_FUNCTION (this << addBaResponseTimeout);
1752  m_addBaResponseTimeout = addBaResponseTimeout;
1753 }
1754 
1755 Time
1757 {
1758  return m_addBaResponseTimeout;
1759 }
1760 
1761 void
1763 {
1764  NS_LOG_FUNCTION (this << failedAddBaTimeout);
1765  m_failedAddBaTimeout = failedAddBaTimeout;
1766 }
1767 
1768 Time
1770 {
1771  return m_failedAddBaTimeout;
1772 }
1773 
1774 bool
1776 {
1777  return true;
1778 }
1779 
1780 } //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:1132
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:1474
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:1739
void VerifyBlockAck(void)
Verifies if dequeued packet has to be transmitted with ack policy Block Ack.
Definition: qos-txop.cc:1459
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:1393
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:1006
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:1580
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:1655
#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:1437
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:1370
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:1587
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:1196
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:1333
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:1317
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:1756
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:1302
void SetAmpduExist(Mac48Address dest, bool enableAmpdu)
Set indication whether A-MPDU is used to transmit data to a peer station.
Definition: qos-txop.cc:1485
void StartAccessIfNeeded(void)
Request access from DCF manager if needed.
Definition: qos-txop.cc:977
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:1762
void SendBlockAckRequest(const Bar &bar)
After that all packets, for which a block ack agreement was established, have been transmitted...
Definition: qos-txop.cc:1540
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:1419
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:1287
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:1409
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:1775
uint32_t GetNTxopFragment(void) const
Calculate the number of TXOP fragments needed for the transmission of the current packet...
Definition: qos-txop.cc:1229
Mac48Address recipient
recipient
void SetAddBaResponseTimeout(Time addBaResponseTimeout)
Set the timeout to wait for ADDBA response.
Definition: qos-txop.cc:1749
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
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
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:1713
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:1509
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:1703
Ptr< const Packet > m_currentPacket
the current packet
Definition: txop.h:526
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
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:1145
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:1572
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:1242
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:1445
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:1033
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:1492
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:1377
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:1563
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:1692
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:1116
bool NeedFragmentation(void) const
Check if the current packet should be fragmented.
Definition: qos-txop.cc:1155
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:1181
Ptr< Packet > GetFragmentPacket(WifiMacHeader *hdr)
Get the next fragment from the packet with appropriate Wifi header for the fragment.
Definition: qos-txop.cc:1349
Time GetFailedAddBaTimeout(void) const
Get the timeout for failed BA agreement.
Definition: qos-txop.cc:1769
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:1520
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:1268
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:1723
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:1594
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.