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"
42 #include "wifi-psdu.h"
43 
44 #undef NS_LOG_APPEND_CONTEXT
45 #define NS_LOG_APPEND_CONTEXT if (m_low != 0) { std::clog << "[mac=" << m_low->GetAddress () << "] "; }
46 
47 namespace ns3 {
48 
49 NS_LOG_COMPONENT_DEFINE ("QosTxop");
50 
52 
53 TypeId
55 {
56  static TypeId tid = TypeId ("ns3::QosTxop")
57  .SetParent<ns3::Txop> ()
58  .SetGroupName ("Wifi")
59  .AddConstructor<QosTxop> ()
60  .AddAttribute ("UseExplicitBarAfterMissedBlockAck",
61  "Specify whether explicit BlockAckRequest should be sent upon missed BlockAck Response.",
62  BooleanValue (true),
65  .AddAttribute ("AddBaResponseTimeout",
66  "The timeout to wait for ADDBA response after the Ack to "
67  "ADDBA request is received.",
68  TimeValue (MilliSeconds (1)),
71  MakeTimeChecker ())
72  .AddAttribute ("FailedAddBaTimeout",
73  "The timeout after a failed BA agreement. During this "
74  "timeout, the originator resumes sending packets using normal "
75  "MPDU. After that, BA agreement is reset and the originator "
76  "will retry BA negotiation.",
77  TimeValue (MilliSeconds (200)),
80  MakeTimeChecker ())
81  .AddAttribute ("BlockAckManager",
82  "The BlockAckManager object.",
83  PointerValue (),
85  MakePointerChecker<BlockAckManager> ())
86  .AddTraceSource ("TxopTrace",
87  "Trace source for TXOP start and duration times",
89  "ns3::TracedValueCallback::Time")
90  ;
91  return tid;
92 }
93 
95  : m_typeOfStation (STA),
96  m_blockAckType (COMPRESSED_BLOCK_ACK),
97  m_startTxop (Seconds (0)),
98  m_isAccessRequestedForRts (false),
99  m_currentIsFragmented (false)
100 {
101  NS_LOG_FUNCTION (this);
102  m_qosBlockedDestinations = Create<QosBlockedDestinations> ();
103  m_baManager = CreateObject<BlockAckManager> ();
104  m_baManager->SetQueue (m_queue);
105  m_baManager->SetBlockAckType (m_blockAckType);
108  m_baManager->SetTxOkCallback (MakeCallback (&QosTxop::BaTxOk, this));
109  m_baManager->SetTxFailedCallback (MakeCallback (&QosTxop::BaTxFailed, this));
110 }
111 
113 {
114  NS_LOG_FUNCTION (this);
115 }
116 
117 void
119 {
120  NS_LOG_FUNCTION (this);
122  m_baManager = 0;
124  Txop::DoDispose ();
125 }
126 
127 bool
129 {
130  return m_baManager->ExistsAgreementInState (address, tid, OriginatorBlockAckAgreement::ESTABLISHED);
131 }
132 
133 uint16_t
135 {
136  return m_baManager->GetRecipientBufferSize (address, tid);
137 }
138 
139 uint16_t
141 {
142  return m_baManager->GetOriginatorStartingSequence (address, tid);
143 }
144 
146 QosTxop::PrepareBlockAckRequest (Mac48Address recipient, uint8_t tid) const
147 {
148  NS_LOG_FUNCTION (this << recipient << +tid);
149 
150  CtrlBAckRequestHeader reqHdr = m_low->GetEdca (tid)->m_baManager->GetBlockAckReqHeader (recipient, tid);
151  Ptr<Packet> bar = Create<Packet> ();
152  bar->AddHeader (reqHdr);
153 
154  WifiMacHeader hdr;
156  hdr.SetAddr1 (recipient);
157  hdr.SetAddr2 (m_low->GetAddress ());
158  hdr.SetDsNotTo ();
159  hdr.SetDsNotFrom ();
160  hdr.SetNoRetry ();
161  hdr.SetNoMoreFragments ();
162 
163  return Create<const WifiMacQueueItem> (bar, hdr);
164 }
165 
166 void
167 QosTxop::ScheduleBar (Ptr<const WifiMacQueueItem> bar, bool skipIfNoDataQueued)
168 {
169  m_baManager->ScheduleBar (bar, skipIfNoDataQueued);
170 }
171 
172 void
174 {
175  Txop::SetWifiRemoteStationManager (remoteManager);
176  NS_LOG_FUNCTION (this << remoteManager);
177  m_baManager->SetWifiRemoteStationManager (m_stationManager);
178 }
179 
180 void
182 {
183  NS_LOG_FUNCTION (this << ackSelector);
184  m_ackPolicySelector = ackSelector;
185 }
186 
189 {
190  return m_ackPolicySelector;
191 }
192 
193 void
195 {
196  NS_LOG_FUNCTION (this << +type);
197  m_typeOfStation = type;
198 }
199 
202 {
203  return m_typeOfStation;
204 }
205 
206 bool
208 {
209  bool ret = (m_currentPacket != 0 || m_baManager->HasPackets () || !m_queue->IsEmpty ());
210  NS_LOG_FUNCTION (this << ret);
211  return ret;
212 }
213 
214 uint16_t
216 {
217  return m_txMiddle->GetNextSequenceNumberFor (hdr);
218 }
219 
220 uint16_t
222 {
223  return m_txMiddle->PeekNextSequenceNumberFor (hdr);
224 }
225 
226 bool
228 {
229  NS_LOG_FUNCTION (this << *mpdu);
230 
231  if (!mpdu->GetHeader ().IsQosData ())
232  {
233  return false;
234  }
235 
236  Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
237  uint8_t tid = mpdu->GetHeader ().GetQosTid ();
238 
239  if (!GetBaAgreementEstablished (recipient, tid))
240  {
241  return false;
242  }
243 
244  if (QosUtilsIsOldPacket (GetBaStartingSequence (recipient, tid),
245  mpdu->GetHeader ().GetSequenceNumber ()))
246  {
247  return true;
248  }
249  return false;
250 }
251 
253 QosTxop::PeekNextFrame (uint8_t tid, Mac48Address recipient)
254 {
255  NS_LOG_FUNCTION (this);
256  WifiMacQueue::ConstIterator it = WifiMacQueue::EMPTY;
257 
258  // lambda to peek the next frame
259  auto peek = [this, &tid, &recipient, &it] (Ptr<WifiMacQueue> queue)
260  {
261  if (tid == 8 && recipient.IsGroup ()) // undefined TID and recipient
262  {
263  return queue->PeekFirstAvailable (m_qosBlockedDestinations, it);
264  }
265  return queue->PeekByTidAndAddress (tid, recipient, it);
266  };
267 
268  // check if there is a packet in the BlockAckManager retransmit queue
269  it = peek (m_baManager->GetRetransmitQueue ());
270  // remove old packets
271  while (it != m_baManager->GetRetransmitQueue ()->end () && IsQosOldPacket (*it))
272  {
273  NS_LOG_DEBUG ("removing an old packet from BlockAckManager retransmit queue: " << **it);
274  it = m_baManager->GetRetransmitQueue ()->Remove (it);
275  it = peek (m_baManager->GetRetransmitQueue ());
276  }
277  if (it != m_baManager->GetRetransmitQueue ()->end ())
278  {
279  NS_LOG_DEBUG ("packet peeked from BlockAckManager retransmit queue: " << **it);
280  return *it;
281  }
282 
283  // otherwise, check if there is a packet in the EDCA queue
284  it = WifiMacQueue::EMPTY;
285  it = peek (m_queue);
286  if (it != m_queue->end ())
287  {
288  // peek the next sequence number and check if it is within the transmit window
289  // in case of QoS data frame
290  uint16_t sequence = m_txMiddle->PeekNextSequenceNumberFor (&(*it)->GetHeader ());
291  if ((*it)->GetHeader ().IsQosData ())
292  {
293  Mac48Address recipient = (*it)->GetHeader ().GetAddr1 ();
294  uint8_t tid = (*it)->GetHeader ().GetQosTid ();
295 
296  if (GetBaAgreementEstablished (recipient, tid)
297  && !IsInWindow (sequence, GetBaStartingSequence (recipient, tid), GetBaBufferSize (recipient, tid)))
298  {
299  NS_LOG_DEBUG ("packet beyond the end of the current transmit window");
300  return 0;
301  }
302  }
303 
304  WifiMacHeader hdr = (*it)->GetHeader ();
305  hdr.SetSequenceNumber (sequence);
306  hdr.SetFragmentNumber (0);
307  hdr.SetNoMoreFragments ();
308  hdr.SetNoRetry ();
309  Ptr<const WifiMacQueueItem> item = Create<const WifiMacQueueItem> ((*it)->GetPacket (), hdr, (*it)->GetTimeStamp ());
310  NS_LOG_DEBUG ("packet peeked from EDCA queue: " << *item);
311  return item;
312  }
313 
314  return 0;
315 }
316 
319  bool aggregate, uint32_t ampduSize, Time ppduDurationLimit)
320 {
321  NS_LOG_FUNCTION (this << peekedItem << txVector << ampduSize << ppduDurationLimit);
322  NS_ASSERT (peekedItem != 0);
323 
324  // do not dequeue the frame if it is a QoS data frame that does not meet the
325  // max A-MPDU size limit (if applicable) or the duration limit (if applicable)
326  if (peekedItem->GetHeader ().IsQosData () &&
327  !m_low->IsWithinSizeAndTimeLimits (peekedItem, txVector, ampduSize, ppduDurationLimit))
328  {
329  return 0;
330  }
331 
332  Mac48Address recipient = peekedItem->GetHeader ().GetAddr1 ();
335  WifiMacQueue::ConstIterator testIt;
336 
337  // the packet can only have been peeked from the block ack manager retransmit
338  // queue if:
339  // - the peeked packet is a QoS Data frame AND
340  // - the peeked packet is not a group addressed frame AND
341  // - an agreement has been established
342  if (peekedItem->GetHeader ().IsQosData () && !recipient.IsGroup ()
343  && GetBaAgreementEstablished (recipient, peekedItem->GetHeader ().GetQosTid ()))
344  {
345  uint8_t tid = peekedItem->GetHeader ().GetQosTid ();
346  testIt = m_baManager->GetRetransmitQueue ()->PeekByTidAndAddress (tid, recipient);
347 
348  if (testIt != m_baManager->GetRetransmitQueue ()->end ())
349  {
350  testItem = *testIt;
351  // if not null, the test packet must equal the peeked packet
352  NS_ASSERT (testItem->GetPacket () == peekedItem->GetPacket ());
353  // we should not be asked to dequeue an old packet
355  testItem->GetHeader ().GetSequenceNumber ()));
356  item = m_baManager->GetRetransmitQueue ()->Dequeue (testIt);
357  NS_LOG_DEBUG ("dequeued from BA manager queue: " << *item);
358  return item;
359  }
360  }
361 
362  // The packet has been peeked from the EDCA queue.
363  // If it is a QoS Data frame and it is not a broadcast frame, attempt A-MSDU
364  // aggregation if aggregate is true
365  if (peekedItem->GetHeader ().IsQosData ())
366  {
367  uint8_t tid = peekedItem->GetHeader ().GetQosTid ();
368  testIt = m_queue->PeekByTidAndAddress (tid, recipient);
369 
370  NS_ASSERT (testIt != m_queue->end () && (*testIt)->GetPacket () == peekedItem->GetPacket ());
371 
372  uint16_t sequence = m_txMiddle->PeekNextSequenceNumberFor (&peekedItem->GetHeader ());
373 
374  // check if the peeked packet is within the transmit window
375  if (GetBaAgreementEstablished (recipient, tid)
376  && !IsInWindow (sequence, GetBaStartingSequence (recipient, tid), GetBaBufferSize (recipient, tid)))
377  {
378  NS_LOG_DEBUG ("packet beyond the end of the current transmit window");
379  return 0;
380  }
381 
382  // try A-MSDU aggregation
383  if (m_low->GetMsduAggregator () != 0 && !recipient.IsGroup () && aggregate)
384  {
385  item = m_low->GetMsduAggregator ()->GetNextAmsdu (recipient, tid, txVector, ampduSize, ppduDurationLimit);
386  }
387 
388  if (item != 0)
389  {
390  NS_LOG_DEBUG ("tx unicast A-MSDU");
391  }
392  else // aggregation was not attempted or failed
393  {
394  item = m_queue->Dequeue (testIt);
395  }
396  }
397  else
398  {
399  // the peeked packet is a non-QoS Data frame (e.g., a DELBA Request), hence
400  // it was not peeked by TID, hence it must be the head of the queue
401  item = m_queue->DequeueFirstAvailable (m_qosBlockedDestinations);
402  NS_ASSERT (item != 0 && item->GetPacket () == peekedItem->GetPacket ());
403  }
404 
405  NS_ASSERT (item != 0);
406 
407  // Assign a sequence number to the MSDU or A-MSDU dequeued from the EDCA queue
408  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&item->GetHeader ());
409  item->GetHeader ().SetSequenceNumber (sequence);
410  item->GetHeader ().SetFragmentNumber (0);
411  item->GetHeader ().SetNoMoreFragments ();
412  item->GetHeader ().SetNoRetry ();
413  NS_LOG_DEBUG ("dequeued from EDCA queue: " << *item);
414 
415  return item;
416 }
417 
420 {
421  NS_LOG_FUNCTION (this << *frame);
422 
424  Mac48Address recipient = frame->GetHeader ().GetAddr1 ();
425 
426  params.DisableNextData ();
427 
428  // group addressed frames
429  if (recipient.IsGroup ())
430  {
431  params.DisableRts ();
432  params.DisableAck ();
433  return params;
434  }
435  if (frame->GetHeader ().IsMgt ())
436  {
437  params.DisableRts ();
438  params.EnableAck ();
439  return params;
440  }
441 
442  // Enable/disable RTS
443  if (!frame->GetHeader ().IsBlockAckReq ()
444  && m_stationManager->NeedRts (frame->GetHeader (), frame->GetSize ())
445  && !m_low->IsCfPeriod ())
446  {
447  params.EnableRts ();
448  }
449  else
450  {
451  params.DisableRts ();
452  }
453 
454  // Select ack technique.
455  if (frame->GetHeader ().IsQosData ())
456  {
457  // Assume normal Ack by default
458  params.EnableAck ();
459  }
460  else if (frame->GetHeader ().IsBlockAckReq ())
461  {
462  // assume a BlockAck variant. Later, if this frame is not aggregated,
463  // the acknowledgment type will be switched to normal Ack
465  {
467  }
469  {
470  CtrlBAckRequestHeader baReqHdr;
471  frame->GetPacket ()->PeekHeader (baReqHdr);
472  uint8_t tid = baReqHdr.GetTidInfo ();
473 
474  if (GetBaBufferSize (recipient, tid) > 64)
475  {
477  }
478  else
479  {
481  }
482  }
484  {
485  NS_FATAL_ERROR ("Multi-tid block ack is not supported");
486  }
487  }
488 
489  return params;
490 }
491 
492 void
494 {
495  NS_LOG_FUNCTION (this << *mpdu);
496  m_currentPacket = mpdu->GetPacket ();
497  m_currentHdr = mpdu->GetHeader ();
498  m_currentPacketTimestamp = mpdu->GetTimeStamp ();
499 }
500 
501 void
503 {
504  NS_LOG_FUNCTION (this);
506  m_accessRequested = false;
509  // discard the current packet if it is a QoS Data frame with expired lifetime
510  if (m_currentPacket != 0 && m_currentHdr.IsQosData ()
511  && (m_currentPacketTimestamp + m_queue->GetMaxDelay () < Simulator::Now ()))
512  {
513  NS_LOG_DEBUG ("the lifetime of current packet expired");
514  m_currentPacket = 0;
515  }
516  // If the current packet is a QoS Data frame, then there must be no block ack agreement
517  // established with the receiver for the TID of the packet. Indeed, retransmission
518  // of MPDUs sent under a block ack agreement is handled through the retransmit queue.
521 
522  if (m_currentPacket == 0)
523  {
524  Ptr<const WifiMacQueueItem> peekedItem = m_baManager->GetBar ();
525  if (peekedItem != 0)
526  {
527  m_currentHdr = peekedItem->GetHeader ();
528  m_currentPacket = peekedItem->GetPacket ();
530  }
531  else
532  {
533  peekedItem = PeekNextFrame ();
534  if (peekedItem == 0)
535  {
536  NS_LOG_DEBUG ("no packets available for transmission");
537  return;
538  }
539  // check if a block ack agreement needs to be established
540  m_currentHdr = peekedItem->GetHeader ();
541  m_currentPacket = peekedItem->GetPacket ();
544  && (!m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
546  && SetupBlockAckIfNeeded ())
547  {
548  return;
549  }
550 
553  // non-group addressed QoS Data frames may be sent in MU PPDUs. Given that at this stage
554  // we do not know the bandwidth it would be given nor the selected acknowledgment
555  // sequence, we cannot determine the constraints on size and duration limit. Hence,
556  // we only peek the non-group addressed QoS Data frame. MacLow will be in charge of
557  // computing the correct limits and dequeue the frame.
558  if (peekedItem->GetHeader ().IsQosData () && !peekedItem->GetHeader ().GetAddr1 ().IsGroup ()
559  && !NeedFragmentation ())
560  {
561  item = Copy (peekedItem);
562  }
563  else
564  {
565  // compute the limit on the PPDU duration due to the TXOP duration, if any
566  Time ppduDurationLimit = Time::Min ();
567  if (peekedItem->GetHeader ().IsQosData () && GetTxopLimit ().IsStrictlyPositive ())
568  {
570  ppduDurationLimit = GetTxopRemaining () - m_low->CalculateOverheadTxTime (peekedItem, params);
571  }
572 
573  // dequeue the peeked item if it fits within the TXOP duration, if any
574  item = DequeuePeekedFrame (peekedItem, m_low->GetDataTxVector (peekedItem),
575  !NeedFragmentation (), 0, ppduDurationLimit);
576  }
577 
578  if (item == 0)
579  {
580  NS_LOG_DEBUG ("Not enough time in the current TXOP");
581  return;
582  }
583  m_currentPacket = item->GetPacket ();
584  m_currentHdr = item->GetHeader ();
585  m_currentPacketTimestamp = item->GetTimeStamp ();
586 
587  m_fragmentNumber = 0;
588  }
589  NS_ASSERT (m_currentPacket != 0);
590  }
591  Ptr<WifiMacQueueItem> mpdu = Create <WifiMacQueueItem> (m_currentPacket, m_currentHdr,
594 
595  if (m_currentHdr.GetAddr1 ().IsGroup ())
596  {
597  NS_LOG_DEBUG ("tx broadcast");
598  m_low->StartTransmission (mpdu, m_currentParams, this);
599  }
600  //With COMPRESSED_BLOCK_ACK fragmentation must be avoided.
601  else if (((m_currentHdr.IsQosData () && !m_currentHdr.IsQosAmsdu ())
602  || (m_currentHdr.IsData () && !m_currentHdr.IsQosData ()))
604  && NeedFragmentation ())
605  {
606  m_currentIsFragmented = true;
608  WifiMacHeader hdr;
609  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
610  if (IsLastFragment ())
611  {
612  NS_LOG_DEBUG ("fragmenting last fragment size=" << fragment->GetSize ());
614  }
615  else
616  {
617  NS_LOG_DEBUG ("fragmenting size=" << fragment->GetSize ());
619  }
620  m_low->StartTransmission (Create<WifiMacQueueItem> (fragment, hdr),
621  m_currentParams, this);
622  }
623  else
624  {
625  m_currentIsFragmented = false;
626  m_low->StartTransmission (mpdu, m_currentParams, this);
627  }
628 }
629 
631 {
632  NS_LOG_FUNCTION (this);
633  bool resetTxop = false;
634  // If an internal collision is experienced, the frame involved may still
635  // be sitting in the queue, and m_currentPacket may still be null.
636  Ptr<const Packet> packet;
637  WifiMacHeader header;
638  if (m_currentPacket == 0)
639  {
641  if (item)
642  {
643  packet = item->GetPacket ();
644  header = item->GetHeader ();
645  }
646  }
647  else
648  {
649  packet = m_currentPacket;
650  header = m_currentHdr;
651  }
652  if (packet != 0)
653  {
655  {
656  if (!NeedRtsRetransmission (packet, header))
657  {
658  resetTxop = true;
659  m_stationManager->ReportFinalRtsFailed (header.GetAddr1 (), &header);
660  }
661  else
662  {
663  m_stationManager->ReportRtsFailed (header.GetAddr1 (), &header);
664  }
665  }
666  else if (header.GetAddr1 () == Mac48Address::GetBroadcast ())
667  {
668  resetTxop = false;
669  }
670  else
671  {
672  if (!NeedDataRetransmission (packet, header))
673  {
674  resetTxop = true;
675  m_stationManager->ReportFinalDataFailed (header.GetAddr1 (), &header, packet->GetSize ());
676  }
677  else
678  {
679  m_stationManager->ReportDataFailed (header.GetAddr1 (), &header, packet->GetSize ());
680  }
681  }
682  if (resetTxop)
683  {
684  NS_LOG_DEBUG ("reset DCF");
685  if (!m_txFailedCallback.IsNull ())
686  {
687  m_txFailedCallback (header);
688  }
689  //to reset the Txop.
690  if (m_currentPacket)
691  {
692  NS_LOG_DEBUG ("Discarding m_currentPacket");
693  m_currentPacket = 0;
694  }
695  else
696  {
697  NS_LOG_DEBUG ("Dequeueing and discarding head of queue");
698  m_queue->Remove ();
699  }
700  ResetCw ();
701  }
702  else
703  {
704  UpdateFailedCw ();
705  }
706  }
707  GenerateBackoff ();
709 }
710 
711 void
713 {
714  NS_LOG_FUNCTION (this);
715  NS_LOG_DEBUG ("missed cts");
716  NS_ASSERT (!mpduList.empty ());
718  {
719  NS_LOG_DEBUG ("Cts Fail");
721  if (!m_txFailedCallback.IsNull ())
722  {
724  }
725  for (auto& mpdu : mpduList)
726  {
727  m_baManager->NotifyDiscardedMpdu (mpdu);
728  }
729  //to reset the Txop.
730  m_currentPacket = 0;
731  ResetCw ();
732  m_cwTrace = GetCw ();
733  }
734  else
735  {
736  UpdateFailedCw ();
737  m_cwTrace = GetCw ();
738  // if a BA agreement is established, store the MPDUs in the block ack manager
739  // retransmission queue. Otherwise, this QosTxop will handle the retransmission
740  // of the (single) frame
741  if (mpduList.size () > 1 ||
742  (mpduList.front ()->GetHeader ().IsQosData ()
743  && GetBaAgreementEstablished (mpduList.front ()->GetHeader ().GetAddr1 (),
744  mpduList.front ()->GetHeader ().GetQosTid ())))
745  {
746  for (auto it = mpduList.rbegin (); it != mpduList.rend (); it++)
747  {
748  m_baManager->GetRetransmitQueue ()->PushFront (*it);
749  }
750  m_currentPacket = 0;
751  }
752  }
753  GenerateBackoff ();
755 }
756 
757 void
759 {
760  NS_LOG_FUNCTION (this);
763  || m_currentHdr.IsQosAmsdu ())
764  {
765  NS_LOG_DEBUG ("got ack. tx done.");
766  if (!m_txOkCallback.IsNull ())
767  {
769  }
770 
771  if (m_currentHdr.IsAction ())
772  {
773  WifiActionHeader actionHdr;
775  p->RemoveHeader (actionHdr);
776  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK)
777  {
779  {
780  MgtDelBaHeader delBa;
781  p->PeekHeader (delBa);
782  if (delBa.IsByOriginator ())
783  {
784  m_baManager->DestroyAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
785  }
786  else
787  {
788  m_low->DestroyBlockAckAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
789  }
790  }
792  {
793  // Setup ADDBA response timeout
794  MgtAddBaRequestHeader addBa;
795  p->PeekHeader (addBa);
798  m_currentHdr.GetAddr1 (), addBa.GetTid ());
799  }
800  }
801  }
803  {
804  // notify the BA manager that the current packet was acknowledged
805  m_baManager->NotifyGotAck (Create<const WifiMacQueueItem> (m_currentPacket, m_currentHdr,
807  }
808  m_currentPacket = 0;
809  ResetCw ();
810  }
811  else
812  {
813  NS_LOG_DEBUG ("got ack. tx not done, size=" << m_currentPacket->GetSize ());
814  }
815 }
816 
817 void
819 {
820  NS_LOG_FUNCTION (this);
821  NS_LOG_DEBUG ("missed ack");
823  {
824  NS_LOG_DEBUG ("Ack Fail");
827  if (!m_txFailedCallback.IsNull ())
828  {
830  }
831  if (m_currentHdr.IsAction ())
832  {
833  WifiActionHeader actionHdr;
834  m_currentPacket->PeekHeader (actionHdr);
835  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK)
836  {
837  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
838  if (m_baManager->ExistsAgreementInState (m_currentHdr.GetAddr1 (), tid, OriginatorBlockAckAgreement::PENDING))
839  {
840  NS_LOG_DEBUG ("No ACK after ADDBA request");
841  m_baManager->NotifyAgreementNoReply (m_currentHdr.GetAddr1 (), tid);
843  }
844  }
845  }
847  {
848  m_baManager->NotifyDiscardedMpdu (Create<const WifiMacQueueItem> (m_currentPacket, m_currentHdr));
849  }
850  m_currentPacket = 0;
851  ResetCw ();
852  m_cwTrace = GetCw ();
853  }
854  else
855  {
856  NS_LOG_DEBUG ("Retransmit");
861  {
862  // notify the BA manager that the current packet was not acknowledged
863  m_baManager->NotifyMissedAck (Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr,
865  // let the BA manager handle its retransmission
866  m_currentPacket = 0;
867  }
868  UpdateFailedCw ();
869  m_cwTrace = GetCw ();
870  }
871  GenerateBackoff ();
873 }
874 
875 void
876 QosTxop::MissedBlockAck (uint8_t nMpdus)
877 {
878  NS_LOG_FUNCTION (this << +nMpdus);
879  /*
880  * If the BlockAck frame is lost, the originator may transmit a BlockAckReq
881  * frame to solicit an immediate BlockAck frame or it may retransmit the Data
882  * frames. (IEEE std 802.11-2016 sec. 10.24.7.7
883  */
884  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
886  {
887  if (NeedBarRetransmission ())
888  {
889  NS_LOG_DEBUG ("Retransmit block ack request");
891  {
893  UpdateFailedCw ();
894  m_cwTrace = GetCw ();
895  }
896  else // missed BlockAck after data frame with Implicit BAR Ack Policy
897  {
899  ScheduleBar (bar);
900  m_currentPacket = 0;
901  }
902  }
903  else
904  {
905  NS_LOG_DEBUG ("Block Ack Request Fail");
906  // if a BA agreement exists, we can get here if there is no outstanding
907  // MPDU whose lifetime has not expired yet.
910  if (m_baManager->ExistsAgreementInState (m_currentHdr.GetAddr1 (), tid,
912  {
913  // If there is any (expired) outstanding MPDU, request the BA manager to discard
914  // it, which involves the scheduling of a BAR to advance the recipient's window
915  if (m_baManager->GetNBufferedPackets (m_currentHdr.GetAddr1 (), tid) > 0)
916  {
917  m_baManager->DiscardOutstandingMpdus (m_currentHdr.GetAddr1 (), tid);
918  }
919  // otherwise, it means that we have not received a BlockAck in response to a
920  // BlockAckRequest sent while no frame was outstanding, whose purpose was therefore
921  // to advance the recipient's window. Schedule a BlockAckRequest with
922  // skipIfNoDataQueued set to true, so that the BlockAckRequest is only sent
923  // if there are data frames queued for this recipient.
924  else
925  {
927  }
928  }
929  //to reset the Txop.
930  m_currentPacket = 0;
931  ResetCw ();
932  m_cwTrace = GetCw ();
933  }
934  }
935  else
936  {
938  {
940  }
941  // implicit BAR and do not use BAR after missed BlockAck, hence try to retransmit data frames
943  {
944  NS_LOG_DEBUG ("Block Ack Fail");
947  if (!m_txFailedCallback.IsNull ())
948  {
950  }
951  if (m_currentHdr.IsAction ())
952  {
953  WifiActionHeader actionHdr;
954  m_currentPacket->PeekHeader (actionHdr);
955  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK)
956  {
957  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
958  if (m_baManager->ExistsAgreementInState (m_currentHdr.GetAddr1 (), tid, OriginatorBlockAckAgreement::PENDING))
959  {
960  NS_LOG_DEBUG ("No ACK after ADDBA request");
961  m_baManager->NotifyAgreementNoReply (m_currentHdr.GetAddr1 (), tid);
963  }
964  }
965  }
966  //to reset the Txop.
967  m_baManager->DiscardOutstandingMpdus (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr));
968  m_currentPacket = 0;
969  ResetCw ();
970  m_cwTrace = GetCw ();
971  }
972  else
973  {
974  NS_LOG_DEBUG ("Retransmit");
976  m_baManager->NotifyMissedBlockAck (m_currentHdr.GetAddr1 (), tid);
977  m_currentPacket = 0;
978  UpdateFailedCw ();
979  m_cwTrace = GetCw ();
980  }
981  }
982  GenerateBackoff ();
984 }
985 
986 void
988 {
989  NS_LOG_FUNCTION (this);
990 
991  // check if the BA manager retransmit queue is empty, so that expired
992  // frames (if any) are removed and a BlockAckRequest is scheduled to advance
993  // the starting sequence number of the transmit (and receiver) window
994  bool baManagerHasPackets = m_baManager->HasPackets ();
995  // remove MSDUs with expired lifetime starting from the head of the queue
996  bool queueIsNotEmpty = !m_queue->IsEmpty ();
997 
998  if ((m_currentPacket != 0 || baManagerHasPackets || queueIsNotEmpty)
999  && !IsAccessRequested ())
1000  {
1002  if (m_currentPacket != 0)
1003  {
1004  item = Create<const WifiMacQueueItem> (m_currentPacket, m_currentHdr);
1005  }
1006  else
1007  {
1008  item = PeekNextFrame ();
1009  }
1010  if (item != 0)
1011  {
1012  m_isAccessRequestedForRts = m_stationManager->NeedRts (item->GetHeader (), item->GetSize ());
1013  }
1014  else
1015  {
1016  m_isAccessRequestedForRts = false;
1017  }
1019  }
1020 }
1021 
1022 void
1024 {
1025  NS_LOG_FUNCTION (this);
1026 
1027  // check if the BA manager retransmit queue is empty, so that expired
1028  // frames (if any) are removed and a BlockAckRequest is scheduled to advance
1029  // the starting sequence number of the transmit (and receiver) window
1030  bool baManagerHasPackets = m_baManager->HasPackets ();
1031  // remove MSDUs with expired lifetime starting from the head of the queue
1032  bool queueIsNotEmpty = !m_queue->IsEmpty ();
1033 
1034  if (m_currentPacket == 0
1035  && (baManagerHasPackets || queueIsNotEmpty)
1036  && !IsAccessRequested ())
1037  {
1039  if (item != 0)
1040  {
1041  m_isAccessRequestedForRts = m_stationManager->NeedRts (item->GetHeader (), item->GetSize ());
1042  }
1043  else
1044  {
1045  m_isAccessRequestedForRts = false;
1046  }
1048  }
1049 }
1050 
1051 bool
1053 {
1054  uint8_t tid = 0;
1055  if (m_currentHdr.IsQosData ())
1056  {
1057  tid = m_currentHdr.GetQosTid ();
1058  }
1059  else if (m_currentHdr.IsBlockAckReq ())
1060  {
1061  CtrlBAckRequestHeader baReqHdr;
1062  m_currentPacket->PeekHeader (baReqHdr);
1063  tid = baReqHdr.GetTidInfo ();
1064  }
1065  else if (m_currentHdr.IsBlockAck ())
1066  {
1067  CtrlBAckResponseHeader baRespHdr;
1068  m_currentPacket->PeekHeader (baRespHdr);
1069  tid = baRespHdr.GetTidInfo ();
1070  }
1071  return m_baManager->NeedBarRetransmission (tid, m_currentHdr.GetAddr1 ());
1072 }
1073 
1074 void
1076 {
1077  NS_LOG_FUNCTION (this);
1078  NS_ASSERT (GetTxopLimit ().IsStrictlyPositive () && GetTxopRemaining ().IsStrictlyPositive ());
1079 
1080  m_currentPacket = 0;
1081  // peek the next BlockAckReq, if any
1082  Ptr<const WifiMacQueueItem> nextFrame = m_baManager->GetBar (false);
1083 
1084  if (nextFrame == 0)
1085  {
1086  nextFrame = PeekNextFrame ();
1087  }
1088 
1089  if (nextFrame != 0)
1090  {
1092 
1093  if (GetTxopRemaining () >= m_low->CalculateOverallTxTime (nextFrame->GetPacket (), &nextFrame->GetHeader (), params))
1094  {
1095  // check if a block ack agreement needs to be established
1096  m_currentHdr = nextFrame->GetHeader ();
1097  m_currentPacket = nextFrame->GetPacket ();
1100  && (!m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
1102  && SetupBlockAckIfNeeded ())
1103  {
1104  return;
1105  }
1106 
1107  Ptr<WifiMacQueueItem> item;
1108  if (nextFrame->GetHeader ().IsBlockAckReq ())
1109  {
1110  item = Copy (m_baManager->GetBar ());
1111  }
1112  // non-group addressed QoS Data frames may be sent in MU PPDUs. Given that at this stage
1113  // we do not know the bandwidth it would be given nor the selected acknowledgment
1114  // sequence, we cannot determine the constraints on size and duration limit. Hence,
1115  // we only peek the non-group addressed QoS Data frame. MacLow will be in charge of
1116  // computing the correct limits and dequeue the frame.
1117  else if (nextFrame->GetHeader ().IsQosData () && !nextFrame->GetHeader ().GetAddr1 ().IsGroup ())
1118  {
1119  item = Copy (nextFrame);
1120  }
1121  else
1122  {
1123  // dequeue the peeked frame
1124  item = DequeuePeekedFrame (nextFrame, m_low->GetDataTxVector (nextFrame));
1125  }
1126 
1127  NS_ASSERT (item != 0);
1128  NS_LOG_DEBUG ("start next packet " << *item << " within the current TXOP");
1129  m_currentPacket = item->GetPacket ();
1130  m_currentHdr = item->GetHeader ();
1131  m_currentPacketTimestamp = item->GetTimeStamp ();
1132  NS_ASSERT (m_currentPacket != 0);
1133 
1134  m_currentParams = params;
1136  m_fragmentNumber = 0;
1137  GetLow ()->StartTransmission (item, m_currentParams, this);
1138  return;
1139  }
1140  }
1141 
1142  // terminate TXOP because no (suitable) frame was found
1143  TerminateTxop ();
1144 }
1145 
1146 void
1148 {
1149  NS_LOG_FUNCTION (this);
1150  if (GetTxopLimit ().IsStrictlyPositive ())
1151  {
1152  NS_LOG_DEBUG ("Terminating TXOP. Duration = " << Simulator::Now () - m_startTxop);
1154  }
1155  GenerateBackoff ();
1157 }
1158 
1159 Time
1161 {
1162  Time remainingTxop = GetTxopLimit ();
1163  remainingTxop -= (Simulator::Now () - m_startTxop);
1164  if (remainingTxop.IsStrictlyNegative ())
1165  {
1166  remainingTxop = Seconds (0);
1167  }
1168  NS_LOG_FUNCTION (this << remainingTxop);
1169  return remainingTxop;
1170 }
1171 
1172 void
1174 {
1175  NS_LOG_FUNCTION (this);
1176  NS_LOG_DEBUG ("a transmission that did not require an ACK just finished");
1177  m_currentPacket = 0;
1178  ResetCw ();
1179  TerminateTxop ();
1180 }
1181 
1182 bool
1184 {
1185  NS_LOG_FUNCTION (this);
1190  && m_currentHdr.IsQosData ()
1192  && GetLow ()->GetMpduAggregator () != 0
1193  && GetLow ()->GetMpduAggregator ()->GetMaxAmpduSize (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr),
1195  {
1196  //MSDU is not fragmented when it is transmitted using an HT-immediate or
1197  //HT-delayed block ack agreement or when it is carried in an A-MPDU.
1198  return false;
1199  }
1200  bool needTxopFragmentation = false;
1202  {
1203  needTxopFragmentation = (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams) > GetTxopLimit ());
1204  }
1205  return (needTxopFragmentation || m_stationManager->NeedFragmentation (m_currentHdr.GetAddr1 (), &m_currentHdr, m_currentPacket));
1206 }
1207 
1208 bool
1210 {
1211  if (GetTxopLimit ().IsZero ())
1212  {
1213  return false;
1214  }
1217  {
1218  return true;
1219  }
1220  return false;
1221 }
1222 
1223 uint32_t
1225 {
1226  Time txopDuration = GetTxopLimit ();
1227  if (txopDuration.IsZero ())
1228  {
1229  return 0;
1230  }
1231  uint32_t maxSize = m_currentPacket->GetSize ();
1232  uint32_t minSize = 0;
1233  uint32_t size = 0;
1234  bool found = false;
1235  while (!found)
1236  {
1237  size = (minSize + ((maxSize - minSize) / 2));
1238  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) > txopDuration)
1239  {
1240  maxSize = size;
1241  }
1242  else
1243  {
1244  minSize = size;
1245  }
1246  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) <= txopDuration
1247  && GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size + 1) > txopDuration)
1248  {
1249  found = true;
1250  }
1251  }
1252  NS_ASSERT (size != 0);
1253  return size;
1254 }
1255 
1256 uint32_t
1258 {
1259  uint32_t fragmentSize = GetTxopFragmentSize ();
1260  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1261  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1262  {
1263  nFragments++;
1264  }
1265  NS_LOG_DEBUG ("GetNTxopFragment returning " << nFragments);
1266  return nFragments;
1267 }
1268 
1269 uint32_t
1270 QosTxop::GetTxopFragmentOffset (uint32_t fragmentNumber) const
1271 {
1272  if (fragmentNumber == 0)
1273  {
1274  return 0;
1275  }
1276  uint32_t offset = 0;
1277  uint32_t fragmentSize = GetTxopFragmentSize ();
1278  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1279  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1280  {
1281  nFragments++;
1282  }
1283  if (fragmentNumber < nFragments)
1284  {
1285  offset = (fragmentNumber * fragmentSize);
1286  }
1287  else
1288  {
1289  NS_ASSERT (false);
1290  }
1291  NS_LOG_DEBUG ("GetTxopFragmentOffset returning " << offset);
1292  return offset;
1293 }
1294 
1295 uint32_t
1296 QosTxop::GetNextTxopFragmentSize (uint32_t fragmentNumber) const
1297 {
1298  NS_LOG_FUNCTION (this << fragmentNumber);
1299  uint32_t fragmentSize = GetTxopFragmentSize ();
1300  uint32_t nFragments = GetNTxopFragment ();
1301  if (fragmentNumber >= nFragments)
1302  {
1303  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning 0");
1304  return 0;
1305  }
1306  if (fragmentNumber == nFragments - 1)
1307  {
1308  fragmentSize = (m_currentPacket->GetSize () - ((nFragments - 1) * fragmentSize));
1309  }
1310  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning " << fragmentSize);
1311  return fragmentSize;
1312 }
1313 
1314 uint32_t
1316 {
1317  uint32_t size;
1318  if (IsTxopFragmentation ())
1319  {
1321  }
1322  else
1323  {
1325  }
1326  return size;
1327 }
1328 
1329 uint32_t
1331 {
1332  uint32_t size;
1333  if (IsTxopFragmentation ())
1334  {
1336  }
1337  else
1338  {
1340  }
1341  return size;
1342 }
1343 
1344 uint32_t
1346 {
1347  uint32_t offset;
1348  if (IsTxopFragmentation ())
1349  {
1351  }
1352  else
1353  {
1356  }
1357  return offset;
1358 }
1359 
1360 bool
1362 {
1363  bool isLastFragment;
1364  if (IsTxopFragmentation ())
1365  {
1366  isLastFragment = (m_fragmentNumber == GetNTxopFragment () - 1);
1367  }
1368  else
1369  {
1372  }
1373  return isLastFragment;
1374 }
1375 
1378 {
1379  NS_LOG_FUNCTION (this << hdr);
1380  *hdr = m_currentHdr;
1382  uint32_t startOffset = GetFragmentOffset ();
1383  Ptr<Packet> fragment;
1384  if (IsLastFragment ())
1385  {
1386  hdr->SetNoMoreFragments ();
1387  }
1388  else
1389  {
1390  hdr->SetMoreFragments ();
1391  }
1392  fragment = m_currentPacket->CreateFragment (startOffset,
1393  GetFragmentSize ());
1394  return fragment;
1395 }
1396 
1397 void
1399 {
1400  NS_LOG_FUNCTION (this << +ac);
1401  m_ac = ac;
1402 }
1403 
1406 {
1407  NS_LOG_FUNCTION (this << &hdr);
1408  Mac48Address retval;
1409  if (GetTypeOfStation () == STA || GetTypeOfStation () == ADHOC_STA)
1410  {
1411  retval = hdr.GetAddr2 ();
1412  }
1413  else
1414  {
1415  retval = hdr.GetAddr3 ();
1416  }
1417  return retval;
1418 }
1419 
1422 {
1423  NS_LOG_FUNCTION (this << &hdr);
1424  Mac48Address retval;
1425  if (GetTypeOfStation () == AP || GetTypeOfStation () == ADHOC_STA)
1426  {
1427  retval = hdr.GetAddr1 ();
1428  }
1429  else
1430  {
1431  retval = hdr.GetAddr3 ();
1432  }
1433  return retval;
1434 }
1435 
1436 void
1438 {
1439  NS_LOG_FUNCTION (this << packet << &hdr);
1440  WifiMacTrailer fcs;
1441  m_queue->PushFront (Create<WifiMacQueueItem> (packet, hdr));
1443 }
1444 
1445 void
1447 {
1448  NS_LOG_FUNCTION (this << respHdr << recipient);
1449  uint8_t tid = respHdr->GetTid ();
1450  if (respHdr->GetStatusCode ().IsSuccess ())
1451  {
1452  NS_LOG_DEBUG ("block ack agreement established with " << recipient);
1453  // Even though a (destination, TID) pair is "blocked" (i.e., no more packets
1454  // are sent) when an Add BA Request is sent to the destination,
1455  // the current packet may still be non-null when the Add BA Response is received.
1456  // In fact, if the Add BA Request timer expires, the (destination, TID) pair is
1457  // "unblocked" and packets to the destination are sent again (under normal
1458  // ack policy). Thus, there may be a packet needing to be retransmitted
1459  // when the Add BA Response is received. If this is the case, let the block
1460  // ack manager handle its retransmission.
1461  if (m_currentPacket != 0 && m_currentHdr.IsQosData ()
1462  && m_currentHdr.GetAddr1 () == recipient && m_currentHdr.GetQosTid () == tid)
1463  {
1464  Ptr<WifiMacQueueItem> mpdu = Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr,
1466  m_baManager->GetRetransmitQueue ()->Enqueue (mpdu);
1467  m_currentPacket = 0;
1468  }
1469  m_baManager->UpdateAgreement (respHdr, recipient);
1470  }
1471  else
1472  {
1473  NS_LOG_DEBUG ("discard ADDBA response" << recipient);
1474  m_baManager->NotifyAgreementRejected (recipient, tid);
1475  }
1477 }
1478 
1479 void
1481 {
1482  NS_LOG_FUNCTION (this << delBaHdr << recipient);
1483  NS_LOG_DEBUG ("received DELBA frame from=" << recipient);
1484  m_baManager->DestroyAgreement (recipient, delBaHdr->GetTid ());
1485 }
1486 
1487 void
1488 QosTxop::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, double dataSnr, WifiTxVector dataTxVector)
1489 {
1490  NS_LOG_FUNCTION (this << blockAck << recipient << rxSnr << dataSnr << dataTxVector);
1491  NS_LOG_DEBUG ("got block ack from=" << recipient);
1492  m_baManager->NotifyGotBlockAck (blockAck, recipient, rxSnr, dataSnr, dataTxVector);
1493  if (!m_txOkCallback.IsNull ())
1494  {
1496  }
1497  m_currentPacket = 0;
1498  ResetCw ();
1499 }
1500 
1502 {
1503  NS_LOG_FUNCTION (this << dest);
1504  auto it = m_aMpduEnabled.find (dest);
1505  if (it != m_aMpduEnabled.end ())
1506  {
1507  return it->second;
1508  }
1509  return false;
1510 }
1511 
1512 void QosTxop::SetAmpduExist (Mac48Address dest, bool enableAmpdu)
1513 {
1514  NS_LOG_FUNCTION (this << dest << enableAmpdu);
1515  m_aMpduEnabled[dest] = enableAmpdu;
1516 }
1517 
1518 void
1520 {
1521  NS_ASSERT (mpdu->GetHeader ().IsQosData ());
1522  // If there is an established BA agreement, store the packet in the queue of outstanding packets
1523  if (GetBaAgreementEstablished (mpdu->GetHeader ().GetAddr1 (), mpdu->GetHeader ().GetQosTid ()))
1524  {
1525  m_baManager->StorePacket (mpdu);
1526  }
1527 }
1528 
1529 bool
1531 {
1532  NS_LOG_FUNCTION (this);
1533  uint8_t tid = m_currentHdr.GetQosTid ();
1534  Mac48Address recipient = m_currentHdr.GetAddr1 ();
1535  uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, recipient);
1536  if ((GetBlockAckThreshold () > 0 && packets >= GetBlockAckThreshold ())
1537  || (GetLow ()->GetMpduAggregator () != 0 && GetLow ()->GetMpduAggregator ()->GetMaxAmpduSize (recipient, tid, WIFI_MOD_CLASS_HT) > 0 && packets > 1)
1540  {
1541  /* Block ack setup */
1542  uint16_t startingSequence = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
1543  SendAddBaRequest (recipient, tid, startingSequence, m_blockAckInactivityTimeout, true);
1544  return true;
1545  }
1546  return false;
1547 }
1548 
1549 void
1551 {
1552  NS_LOG_FUNCTION (this);
1553  m_baManager->SetTxMiddle (m_txMiddle);
1554  m_low->RegisterEdcaForAc (m_ac, this);
1555  m_baManager->SetBlockAckInactivityCallback (MakeCallback (&QosTxop::SendDelbaFrame, this));
1556 }
1557 
1558 void
1560 {
1561  NS_LOG_FUNCTION (this << +threshold);
1562  m_blockAckThreshold = threshold;
1563  m_baManager->SetBlockAckThreshold (threshold);
1564 }
1565 
1566 void
1568 {
1569  NS_LOG_FUNCTION (this << timeout);
1571 }
1572 
1573 uint8_t
1575 {
1576  NS_LOG_FUNCTION (this);
1577  return m_blockAckThreshold;
1578 }
1579 
1580 void
1581 QosTxop::SendAddBaRequest (Mac48Address dest, uint8_t tid, uint16_t startSeq,
1582  uint16_t timeout, bool immediateBAck)
1583 {
1584  NS_LOG_FUNCTION (this << dest << +tid << startSeq << timeout << immediateBAck);
1585  NS_LOG_DEBUG ("sent ADDBA request to " << dest);
1586  WifiMacHeader hdr;
1588  hdr.SetAddr1 (dest);
1589  hdr.SetAddr2 (m_low->GetAddress ());
1590  hdr.SetAddr3 (m_low->GetBssid ());
1591  hdr.SetDsNotTo ();
1592  hdr.SetDsNotFrom ();
1593 
1594  WifiActionHeader actionHdr;
1597  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1598 
1599  Ptr<Packet> packet = Create<Packet> ();
1600  /*Setting ADDBARequest header*/
1601  MgtAddBaRequestHeader reqHdr;
1602  reqHdr.SetAmsduSupport (true);
1603  if (immediateBAck)
1604  {
1605  reqHdr.SetImmediateBlockAck ();
1606  }
1607  else
1608  {
1609  reqHdr.SetDelayedBlockAck ();
1610  }
1611  reqHdr.SetTid (tid);
1612  /* For now we don't use buffer size field in the ADDBA request frame. The recipient
1613  * will choose how many packets it can receive under block ack.
1614  */
1615  reqHdr.SetBufferSize (0);
1616  reqHdr.SetTimeout (timeout);
1617  reqHdr.SetStartingSequence (startSeq);
1618 
1619  m_baManager->CreateAgreement (&reqHdr, dest);
1620 
1621  packet->AddHeader (reqHdr);
1622  packet->AddHeader (actionHdr);
1623 
1624  m_currentPacket = packet;
1625  m_currentHdr = hdr;
1626 
1627  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
1628  m_currentHdr.SetSequenceNumber (sequence);
1633 
1637 
1638  m_low->StartTransmission (Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr), m_currentParams, this);
1639 }
1640 
1641 void
1642 QosTxop::SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator)
1643 {
1644  NS_LOG_FUNCTION (this << addr << +tid << byOriginator);
1645  WifiMacHeader hdr;
1647  hdr.SetAddr1 (addr);
1648  hdr.SetAddr2 (m_low->GetAddress ());
1649  hdr.SetAddr3 (m_low->GetBssid ());
1650  hdr.SetDsNotTo ();
1651  hdr.SetDsNotFrom ();
1652 
1653  MgtDelBaHeader delbaHdr;
1654  delbaHdr.SetTid (tid);
1655  if (byOriginator)
1656  {
1657  delbaHdr.SetByOriginator ();
1658  m_baManager->DestroyAgreement (addr, tid);
1659  }
1660  else
1661  {
1662  delbaHdr.SetByRecipient ();
1663  m_low->DestroyBlockAckAgreement (addr, tid);
1664  }
1665 
1666  WifiActionHeader actionHdr;
1669  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1670 
1671  Ptr<Packet> packet = Create<Packet> ();
1672  packet->AddHeader (delbaHdr);
1673  packet->AddHeader (actionHdr);
1674 
1675  PushFront (packet, hdr);
1676 }
1677 
1678 void
1680 {
1681  NS_LOG_FUNCTION (this);
1682  ResetCw ();
1683  m_cwTrace = GetCw ();
1684  GenerateBackoff ();
1685 }
1686 
1687 void
1689 {
1690  NS_LOG_FUNCTION (this << hdr);
1691  if (!m_txOkCallback.IsNull ())
1692  {
1694  }
1695 }
1696 
1697 void
1699 {
1700  NS_LOG_FUNCTION (this << hdr);
1701  if (!m_txFailedCallback.IsNull ())
1702  {
1704  }
1705 }
1706 
1707 void
1709 {
1710  NS_LOG_FUNCTION (this << recipient << +tid);
1711  // If agreement is still pending, ADDBA response is not received
1712  if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::PENDING))
1713  {
1714  m_baManager->NotifyAgreementNoReply (recipient, tid);
1715  Simulator::Schedule (m_failedAddBaTimeout, &QosTxop::ResetBa, this, recipient, tid);
1716  GenerateBackoff ();
1718  }
1719 }
1720 
1721 void
1722 QosTxop::ResetBa (Mac48Address recipient, uint8_t tid)
1723 {
1724  NS_LOG_FUNCTION (this << recipient << +tid);
1725  // This function is scheduled when waiting for an ADDBA response. However,
1726  // before this function is called, a DELBA request may arrive, which causes
1727  // the agreement to be deleted. Hence, check if an agreement exists before
1728  // notifying that the agreement has to be reset.
1729  if (m_baManager->ExistsAgreement (recipient, tid)
1730  && !m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED))
1731  {
1732  m_baManager->NotifyAgreementReset (recipient, tid);
1733  }
1734 }
1735 
1736 void
1738 {
1739  NS_LOG_FUNCTION (this << addBaResponseTimeout);
1740  m_addBaResponseTimeout = addBaResponseTimeout;
1741 }
1742 
1743 Time
1745 {
1746  return m_addBaResponseTimeout;
1747 }
1748 
1749 void
1751 {
1752  NS_LOG_FUNCTION (this << failedAddBaTimeout);
1753  m_failedAddBaTimeout = failedAddBaTimeout;
1754 }
1755 
1756 Time
1758 {
1759  return m_failedAddBaTimeout;
1760 }
1761 
1762 bool
1764 {
1765  return true;
1766 }
1767 
1768 } //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:531
TxFailed m_txFailedCallback
the transmit failed callback
Definition: txop.h:507
void ScheduleBar(Ptr< const WifiMacQueueItem > bar, bool skipIfNoDataQueued=false)
Definition: qos-txop.cc:167
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
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
void MissedAck(void)
Event handler when an Ack is missed.
Definition: qos-txop.cc:818
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:253
void SetMoreFragments(void)
Set the More Fragment bit in the Frame Control field.
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
Time GetTxopRemaining(void) const
Return the remaining duration in the current TXOP.
Definition: qos-txop.cc:1160
bool GetVhtSupported(void) const
Return whether the device has VHT capability support enabled.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#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:1501
Ptr< MacTxMiddle > m_txMiddle
the MacTxMiddle
Definition: txop.h:510
void ResetBa(Mac48Address recipient, uint8_t tid)
Reset BA agreement after BA negotiation failed.
Definition: qos-txop.cc:1722
AttributeValue implementation for Boolean.
Definition: boolean.h:36
void RestartAccessIfNeeded(void)
Restart access request if needed.
Definition: qos-txop.cc:987
TracedValue< uint32_t > m_cwTrace
CW trace value.
Definition: txop.h:536
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
BlockAckType m_blockAckType
the BlockAck type
Definition: qos-txop.h:539
#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.
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:273
Time m_startTxop
the start TXOP time
Definition: qos-txop.h:542
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
Definition: mgt-headers.h:870
Mac48Address MapDestAddressForAggregation(const WifiMacHeader &hdr)
This functions are used only to correctly set destination address in A-MSDU subframes.
Definition: qos-txop.cc:1421
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:85
bool m_isAccessRequestedForRts
flag whether access is requested to transmit a RTS frame
Definition: qos-txop.h:543
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:92
void MissedBlockAck(uint8_t nMpdus)
Event handler when a BlockAck timeout has occurred.
Definition: qos-txop.cc:876
Implement the header for management frames of type Add Block Ack request.
Definition: mgt-headers.h:1003
bool NeedBarRetransmission(void)
Check if BlockAckRequest should be re-transmitted.
Definition: qos-txop.cc:1052
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:505
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:205
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1286
void RequestAccess(Ptr< Txop > txop, bool isCfPeriod=false)
void SetBlockAckInactivityTimeout(uint16_t timeout)
Set the BlockAck inactivity timeout.
Definition: qos-txop.cc:1567
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:1642
Ptr< WifiAckPolicySelector > GetAckPolicySelector(void) const
Return the ack policy selector.
Definition: qos-txop.cc:188
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
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
Exactly equivalent to t > 0.
Definition: nstime.h:332
uint16_t GetBaStartingSequence(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:140
void GotDelBaFrame(const MgtDelBaHeader *delBaHdr, Mac48Address recipient)
Event handler when a DELBA frame is received.
Definition: qos-txop.cc:1480
void UpdateFragmentationThreshold(void)
Typically called to update the fragmentation threshold at the start of a new transmission.
bool IsLastFragment(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, uint32_t fragmentNumber)
CategoryValue GetCategory()
Return the category value.
virtual ~QosTxop()
Definition: qos-txop.cc:112
ns3::Time timeout
virtual void GenerateBackoff(void)
Generate a new backoff now.
Definition: txop.cc:553
void SetAccessCategory(AcIndex ac)
Set the access category of this EDCAF.
Definition: qos-txop.cc:1398
static TypeId GetTypeId(void)
Get the type ID.
Definition: qos-txop.cc:54
uint8_t GetBlockAckThreshold(void) const
Return the current threshold for block ack mechanism.
Definition: qos-txop.cc:1574
void DoDispose(void)
Destructor implementation.
Definition: qos-txop.cc:118
uint32_t GetTxopFragmentSize(void) const
Calculate the size of the current TXOP fragment.
Definition: qos-txop.cc:1224
Time m_failedAddBaTimeout
timeout after failed BA agreement
Definition: qos-txop.h:546
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 BlockAck 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:1361
uint8_t GetTid(void) const
Return the Traffic ID (TID).
bool IsBlockAckReq(void) const
Return true if the header is a BlockAckRequest header.
uint32_t GetFragmentOffset(void) const
Calculate the offset for the current fragment.
Definition: qos-txop.cc:1345
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:225
Time GetAddBaResponseTimeout(void) const
Get the timeout for ADDBA response.
Definition: qos-txop.cc:1744
bool IsAction(void) const
Return true if the header is an Action header.
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:227
void GotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, double dataSnr, WifiTxVector dataTxVector)
Event handler when a BlockAck is received.
Definition: qos-txop.cc:1488
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
bool IsZero(void) const
Exactly equivalent to t == 0.
Definition: nstime.h:300
AttributeValue implementation for Time.
Definition: nstime.h:1342
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:1330
void SetAmpduExist(Mac48Address dest, bool enableAmpdu)
Set indication whether A-MPDU is used to transmit data to a peer station.
Definition: qos-txop.cc:1512
void StartAccessIfNeeded(void)
Request access from Txop if needed.
Definition: qos-txop.cc:1023
void SetFailedAddBaTimeout(Time failedAddBaTimeout)
Set the timeout for failed BA agreement.
Definition: qos-txop.cc:1750
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:535
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 BlockAck response.
Definition: ctrl-headers.h:193
void GotAddBaResponse(const MgtAddBaResponseHeader *respHdr, Mac48Address recipient)
Event handler when an ADDBA response is received.
Definition: qos-txop.cc:1446
void SetTypeOfStation(TypeOfStation type)
Set type of station with the given type.
Definition: qos-txop.cc:194
static const ConstIterator EMPTY
Invalid iterator to signal an empty queue.
virtual bool IsAccessRequested(void) const
Definition: txop.cc:463
bool GetQosSupported(Mac48Address address) const
Return whether the given station is QoS capable.
bool NeedRts(const WifiMacHeader &header, uint32_t size)
#define list
uint32_t GetFragmentSize(void) const
Calculate the size of the current fragment.
Definition: qos-txop.cc:1315
uint16_t GetNextSequenceNumberFor(const WifiMacHeader *hdr)
Return the next sequence number for the given header.
Definition: qos-txop.cc:215
void PushFront(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Definition: qos-txop.cc:1437
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:221
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
bool IsQosTxop(void) const
Check for QoS TXOP.
Definition: qos-txop.cc:1763
uint32_t GetNTxopFragment(void) const
Calculate the number of TXOP fragments needed for the transmission of the current packet...
Definition: qos-txop.cc:1257
void SetAddBaResponseTimeout(Time addBaResponseTimeout)
Set the timeout to wait for ADDBA response.
Definition: qos-txop.cc:1737
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:381
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:366
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t GetCw(void) const
Definition: txop.cc:212
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:44
StatusCode GetStatusCode(void) const
Return the status code.
void EnableAck(void)
Wait ACKTimeout for an Ack.
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:1698
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:712
void CompleteMpduTx(Ptr< WifiMacQueueItem > mpdu)
Stores an MPDU (part of an A-MPDU) in block ack agreement (i.e.
Definition: qos-txop.cc:1519
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:509
virtual void DoDispose(void)
Destructor implementation.
Definition: txop.cc:108
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:213
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:419
bool NeedDataRetransmission(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Check if Data should be re-transmitted if Ack was missed.
Definition: txop.cc:388
void BaTxOk(const WifiMacHeader &hdr)
The packet we sent was successfully received by the receiver.
Definition: qos-txop.cc:1688
Ptr< const Packet > m_currentPacket
the current packet
Definition: txop.h:531
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:1343
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:1173
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:195
void SetBlockAckThreshold(uint8_t threshold)
Set threshold for block ack mechanism.
Definition: qos-txop.cc:1559
void UpdateCurrentPacket(Ptr< WifiMacQueueItem > mpdu)
Update the current packet this QosTxop is trying to transmit.
Definition: qos-txop.cc:493
Ptr< MacLow > m_low
the MacLow
Definition: txop.h:511
uint8_t m_blockAckThreshold
the block ack threshold (use BA mechanism if number of packets in queue reaches this value...
Definition: qos-txop.h:536
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > remoteManager)
Set WifiRemoteStationsManager this Txop is associated to.
Definition: qos-txop.cc:173
uint32_t GetTxopFragmentOffset(uint32_t fragmentNumber) const
Calculate the offset for the fragment.
Definition: qos-txop.cc:1270
Ptr< WifiAckPolicySelector > m_ackPolicySelector
the ack policy selector
Definition: qos-txop.h:533
uint8_t GetTid(void) const
Return the Traffic ID (TID).
Ptr< WifiMacQueueItem > DequeuePeekedFrame(Ptr< const WifiMacQueueItem > peekedItem, WifiTxVector txVector, bool aggregate=true, uint32_t ampduSize=0, Time ppduDurationLimit=Time::Min())
Dequeue the frame that has been previously peeked by calling PeekNextFrame.
Definition: qos-txop.cc:318
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
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:227
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:533
virtual bool HasFramesToTransmit(void)
Check if the Txop has frames to transmit.
Definition: qos-txop.cc:207
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:758
void StartNextPacket(void)
Start transmission for the next packet if allowed by the TxopLimit.
Definition: qos-txop.cc:1075
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:519
BlockAckActionValue blockAck
block ack
Definition: mgt-headers.h:946
void Unblock(Mac48Address dest, uint8_t tid)
Un-block the given destination address and TID (e.g.
Implement the header for management frames of type Add Block Ack response.
Definition: mgt-headers.h:1135
bool IsStrictlyNegative(void) const
Exactly equivalent to t < 0.
Definition: nstime.h:324
Implement the header for management frames of type Delete Block Ack.
Definition: mgt-headers.h:1256
Mac48Address MapSrcAddressForAggregation(const WifiMacHeader &hdr)
This functions are used only to correctly set source address in A-MSDU subframes. ...
Definition: qos-txop.cc:1405
bool GetBaAgreementEstablished(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:128
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
bool m_useExplicitBarAfterMissedBlockAck
flag whether explicit BlockAckRequest should be sent upon missed BlockAck Response ...
Definition: qos-txop.h:547
TypeOfStation GetTypeOfStation(void) const
Return type of station.
Definition: qos-txop.cc:201
typedef for union of different ActionValues
Definition: mgt-headers.h:941
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1278
Ptr< const WifiMacQueueItem > PrepareBlockAckRequest(Mac48Address recipient, uint8_t tid) const
Definition: qos-txop.cc:146
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Ptr< QosBlockedDestinations > m_qosBlockedDestinations
the QoS blocked destinations
Definition: qos-txop.h:534
void NotifyAccessGranted(void)
Notify the Txop that access has been granted.
Definition: qos-txop.cc:502
uint16_t GetBaBufferSize(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:134
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:506
void DisableNextData(void)
Do not attempt to send data burst after current transmission.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:472
virtual void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > remoteManager)
Set WifiRemoteStationsManager this Txop is associated to.
Definition: txop.cc:141
void CompleteConfig(void)
Complete block ack configuration.
Definition: qos-txop.cc:1550
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:544
void SetAckPolicySelector(Ptr< WifiAckPolicySelector > ackSelector)
Set the ack policy selector.
Definition: qos-txop.cc:181
uint8_t m_fragmentNumber
the fragment number
Definition: txop.h:534
TracedCallback< Time, Time > m_txopTrace
TXOP trace callback.
Definition: qos-txop.h:549
void DoInitialize(void)
Initialize() implementation.
Definition: qos-txop.cc:1679
uint8_t GetTid(void) const
Return the Traffic ID (TID).
void TerminateTxop(void)
Update backoff and restart access if needed.
Definition: qos-txop.cc:1147
bool NeedFragmentation(void) const
Check if the current packet should be fragmented.
Definition: qos-txop.cc:1183
TypeOfStation
Enumeration for type of station.
Definition: qos-txop.h:47
WifiMacHeader m_currentHdr
the current header
Definition: txop.h:532
Time m_currentPacketTimestamp
the current packet timestamp
Definition: qos-txop.h:540
bool IsTxopFragmentation(void) const
Check if the current packet is fragmented because of an exceeded TXOP duration.
Definition: qos-txop.cc:1209
void EnableBlockAck(BlockAckType type)
Wait the timeout corresponding to the given BlockAck response type.
Ptr< Packet > GetFragmentPacket(WifiMacHeader *hdr)
Get the next fragment from the packet with appropriate Wifi header for the fragment.
Definition: qos-txop.cc:1377
Time GetFailedAddBaTimeout(void) const
Get the timeout for failed BA agreement.
Definition: qos-txop.cc:1757
ActionValue GetAction()
Return the action value.
uint16_t m_blockAckInactivityTimeout
the BlockAck inactivity timeout value (in TUs, i.e.
Definition: qos-txop.h:541
Headers for BlockAckRequest.
Definition: ctrl-headers.h:41
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
Ptr< WifiRemoteStationManager > m_stationManager
the wifi remote station manager
Definition: txop.h:512
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:1530
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 Txop that internal collision has occurred.
Definition: qos-txop.cc:630
void ResetCw(void)
Update the value of the CW variable to take into account a transmission success or a transmission abo...
Definition: txop.cc:218
uint32_t GetNextTxopFragmentSize(uint32_t fragmentNumber) const
Calculate the size of the next TXOP fragment.
Definition: qos-txop.cc:1296
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
TypeOfStation m_typeOfStation
the type of station
Definition: qos-txop.h:532
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:923
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:38
Ptr< T > Copy(Ptr< T > object)
Return a deep copy of a Ptr.
Definition: ptr.h:536
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
void AddBaResponseTimeout(Mac48Address recipient, uint8_t tid)
Callback when ADDBA response is not received after timeout.
Definition: qos-txop.cc:1708
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:545
std::map< Mac48Address, bool > m_aMpduEnabled
list containing flags whether A-MPDU is enabled for a given destination address
Definition: qos-txop.h:102
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:1581
void SetDsNotFrom(void)
Un-set the From DS bit in the Frame Control field.
void ReportAmpduTxStatus(Mac48Address address, uint8_t nSuccessfulMpdus, uint8_t nFailedMpdus, double rxSnr, double dataSnr, WifiTxVector dataTxVector)
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
Handle packet fragmentation and retransmissions for data and management frames.
Definition: txop.h:66
Time GetTxopLimit(void) const
Return the TXOP limit.
Definition: txop.cc:303