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 Block Ack Request should be sent upon missed Block Ack 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 
145 void
147 {
148  m_baManager->ScheduleBlockAckReq (address, tid);
149 }
150 
151 void
153 {
154  Txop::SetWifiRemoteStationManager (remoteManager);
155  NS_LOG_FUNCTION (this << remoteManager);
156  m_baManager->SetWifiRemoteStationManager (m_stationManager);
157 }
158 
159 void
161 {
162  NS_LOG_FUNCTION (this << ackSelector);
163  m_ackPolicySelector = ackSelector;
164 }
165 
168 {
169  return m_ackPolicySelector;
170 }
171 
172 void
174 {
175  NS_LOG_FUNCTION (this << +type);
176  m_typeOfStation = type;
177 }
178 
181 {
182  return m_typeOfStation;
183 }
184 
185 bool
187 {
188  bool ret = (m_currentPacket != 0 || m_baManager->HasPackets () || !m_queue->IsEmpty ());
189  NS_LOG_FUNCTION (this << ret);
190  return ret;
191 }
192 
193 uint16_t
195 {
196  return m_txMiddle->GetNextSequenceNumberFor (hdr);
197 }
198 
199 uint16_t
201 {
202  return m_txMiddle->PeekNextSequenceNumberFor (hdr);
203 }
204 
205 bool
207 {
208  NS_LOG_FUNCTION (this << *mpdu);
209 
210  if (!mpdu->GetHeader ().IsQosData ())
211  {
212  return false;
213  }
214 
215  Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
216  uint8_t tid = mpdu->GetHeader ().GetQosTid ();
217 
218  if (!GetBaAgreementEstablished (recipient, tid))
219  {
220  return false;
221  }
222 
223  if (QosUtilsIsOldPacket (GetBaStartingSequence (recipient, tid),
224  mpdu->GetHeader ().GetSequenceNumber ()))
225  {
226  return true;
227  }
228  return false;
229 }
230 
232 QosTxop::PeekNextFrame (uint8_t tid, Mac48Address recipient)
233 {
234  NS_LOG_FUNCTION (this);
235  WifiMacQueue::ConstIterator it = WifiMacQueue::EMPTY;
236 
237  // lambda to peek the next frame
238  auto peek = [this, &tid, &recipient, &it] (Ptr<WifiMacQueue> queue)
239  {
240  if (tid == 8 && recipient.IsBroadcast ()) // undefined TID and recipient
241  {
242  return queue->PeekFirstAvailable (m_qosBlockedDestinations, it);
243  }
244  return queue->PeekByTidAndAddress (tid, recipient, it);
245  };
246 
247  // check if there is a packet in the BlockAckManager retransmit queue
248  it = peek (m_baManager->GetRetransmitQueue ());
249  // remove old packets
250  while (it != m_baManager->GetRetransmitQueue ()->end () && IsQosOldPacket (*it))
251  {
252  NS_LOG_DEBUG ("removing an old packet from BlockAckManager retransmit queue: " << **it);
253  it = m_baManager->GetRetransmitQueue ()->Remove (it);
254  it = peek (m_baManager->GetRetransmitQueue ());
255  }
256  if (it != m_baManager->GetRetransmitQueue ()->end ())
257  {
258  NS_LOG_DEBUG ("packet peeked from BlockAckManager retransmit queue: " << **it);
259  return *it;
260  }
261 
262  // otherwise, check if there is a packet in the EDCA queue
263  it = WifiMacQueue::EMPTY;
264  it = peek (m_queue);
265  if (it != m_queue->end ())
266  {
267  // peek the next sequence number and check if it is within the transmit window
268  // in case of QoS data frame
269  uint16_t sequence = m_txMiddle->PeekNextSequenceNumberFor (&(*it)->GetHeader ());
270  if ((*it)->GetHeader ().IsQosData ())
271  {
272  Mac48Address recipient = (*it)->GetHeader ().GetAddr1 ();
273  uint8_t tid = (*it)->GetHeader ().GetQosTid ();
274 
275  if (GetBaAgreementEstablished (recipient, tid)
276  && !IsInWindow (sequence, GetBaStartingSequence (recipient, tid), GetBaBufferSize (recipient, tid)))
277  {
278  NS_LOG_DEBUG ("packet beyond the end of the current transmit window");
279  return 0;
280  }
281  }
282 
283  WifiMacHeader hdr = (*it)->GetHeader ();
284  hdr.SetSequenceNumber (sequence);
285  hdr.SetFragmentNumber (0);
286  hdr.SetNoMoreFragments ();
287  hdr.SetNoRetry ();
288  Ptr<const WifiMacQueueItem> item = Create<const WifiMacQueueItem> ((*it)->GetPacket (), hdr, (*it)->GetTimeStamp ());
289  NS_LOG_DEBUG ("packet peeked from EDCA queue: " << *item);
290  return item;
291  }
292 
293  return 0;
294 }
295 
298  bool aggregate, uint32_t ampduSize, Time ppduDurationLimit)
299 {
300  NS_LOG_FUNCTION (this << peekedItem << txVector << ampduSize << ppduDurationLimit);
301  NS_ASSERT (peekedItem != 0);
302 
303  // do not dequeue the frame if it is a QoS data frame that does not meet the
304  // max A-MPDU size limit (if applicable) or the duration limit (if applicable)
305  if (peekedItem->GetHeader ().IsQosData () &&
306  !m_low->IsWithinSizeAndTimeLimits (peekedItem, txVector, ampduSize, ppduDurationLimit))
307  {
308  return 0;
309  }
310 
311  Mac48Address recipient = peekedItem->GetHeader ().GetAddr1 ();
314  WifiMacQueue::ConstIterator testIt;
315 
316  // the packet can only have been peeked from the Block Ack manager retransmit
317  // queue if:
318  // - the peeked packet is a QoS Data frame AND
319  // - the peeked packet is not a broadcast frame AND
320  // - an agreement has been established
321  if (peekedItem->GetHeader ().IsQosData () && !recipient.IsBroadcast ()
322  && GetBaAgreementEstablished (recipient, peekedItem->GetHeader ().GetQosTid ()))
323  {
324  uint8_t tid = peekedItem->GetHeader ().GetQosTid ();
325  testIt = m_baManager->GetRetransmitQueue ()->PeekByTidAndAddress (tid, recipient);
326 
327  if (testIt != m_baManager->GetRetransmitQueue ()->end ())
328  {
329  testItem = *testIt;
330  // if not null, the test packet must equal the peeked packet
331  NS_ASSERT (testItem->GetPacket () == peekedItem->GetPacket ());
332  // we should not be asked to dequeue an old packet
334  testItem->GetHeader ().GetSequenceNumber ()));
335  item = m_baManager->GetRetransmitQueue ()->Dequeue (testIt);
336  NS_LOG_DEBUG ("dequeued from BA manager queue: " << *item);
337  return item;
338  }
339  }
340 
341  // the packet has been peeked from the EDCA queue.
342  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&peekedItem->GetHeader ());
343 
344  // If it is a QoS Data frame and it is not a broadcast frame, attempt A-MSDU
345  // aggregation if aggregate is true
346  if (peekedItem->GetHeader ().IsQosData ())
347  {
348  uint8_t tid = peekedItem->GetHeader ().GetQosTid ();
349  testIt = m_queue->PeekByTidAndAddress (tid, recipient);
350 
351  NS_ASSERT (testIt != m_queue->end () && (*testIt)->GetPacket () == peekedItem->GetPacket ());
352 
353  // check if the peeked packet is within the transmit window
354  if (GetBaAgreementEstablished (recipient, tid)
355  && !IsInWindow (sequence, GetBaStartingSequence (recipient, tid), GetBaBufferSize (recipient, tid)))
356  {
357  NS_LOG_DEBUG ("packet beyond the end of the current transmit window");
358  return 0;
359  }
360 
361  // try A-MSDU aggregation
362  if (m_low->GetMsduAggregator () != 0 && !recipient.IsBroadcast () && aggregate)
363  {
364  item = m_low->GetMsduAggregator ()->GetNextAmsdu (recipient, tid, txVector, ampduSize, ppduDurationLimit);
365  }
366 
367  if (item != 0)
368  {
369  NS_LOG_DEBUG ("tx unicast A-MSDU");
370  }
371  else // aggregation was not attempted or failed
372  {
373  item = m_queue->Dequeue (testIt);
374  }
375  }
376  else
377  {
378  // the peeked packet is a non-QoS Data frame (e.g., a DELBA Request), hence
379  // it was not peeked by TID, hence it must be the head of the queue
380  item = m_queue->DequeueFirstAvailable (m_qosBlockedDestinations);
381  NS_ASSERT (item != 0 && item->GetPacket () == peekedItem->GetPacket ());
382  }
383 
384  // Assign a sequence number to the MSDU or A-MSDU dequeued from the EDCA queue
385  NS_ASSERT (item != 0);
386  item->GetHeader ().SetSequenceNumber (sequence);
387  item->GetHeader ().SetFragmentNumber (0);
388  item->GetHeader ().SetNoMoreFragments ();
389  item->GetHeader ().SetNoRetry ();
390  NS_LOG_DEBUG ("dequeued from EDCA queue: " << *item);
391 
392  return item;
393 }
394 
397 {
398  NS_LOG_FUNCTION (this << *frame);
399 
401  Mac48Address recipient = frame->GetHeader ().GetAddr1 ();
402 
403  params.DisableNextData ();
404 
405  // broadcast frames
406  if (recipient.IsBroadcast ())
407  {
408  params.DisableRts ();
409  params.DisableAck ();
410  return params;
411  }
412  if (frame->GetHeader ().IsMgt ())
413  {
414  params.DisableRts ();
415  params.EnableAck ();
416  return params;
417  }
418 
419  // Enable/disable RTS
420  if (!frame->GetHeader ().IsBlockAckReq ()
421  && m_stationManager->NeedRts (recipient, &frame->GetHeader (),
422  frame->GetPacket (), m_low->GetDataTxVector (frame))
423  && !m_low->IsCfPeriod ())
424  {
425  params.EnableRts ();
426  }
427  else
428  {
429  params.DisableRts ();
430  }
431 
432  // Select ack technique.
433  if (frame->GetHeader ().IsQosData ())
434  {
435  // Assume normal ack by default
436  params.EnableAck ();
437  }
438  else if (frame->GetHeader ().IsBlockAckReq ())
439  {
440  // assume a block ack variant. Later, if this frame is not aggregated,
441  // the acknowledgment type will be switched to normal ack
443  {
445  }
447  {
448  CtrlBAckRequestHeader baReqHdr;
449  frame->GetPacket ()->PeekHeader (baReqHdr);
450  uint8_t tid = baReqHdr.GetTidInfo ();
451 
452  if (GetBaBufferSize (recipient, tid) > 64)
453  {
455  }
456  else
457  {
459  }
460  }
462  {
463  NS_FATAL_ERROR ("Multi-tid block ack is not supported");
464  }
465  }
466 
467  return params;
468 }
469 
470 void
472 {
473  NS_LOG_FUNCTION (this << *mpdu);
474  m_currentPacket = mpdu->GetPacket ();
475  m_currentHdr = mpdu->GetHeader ();
476  m_currentPacketTimestamp = mpdu->GetTimeStamp ();
477 }
478 
479 void
481 {
482  NS_LOG_FUNCTION (this);
484  m_accessRequested = false;
487  // discard the current packet if it is a QoS Data frame with expired lifetime
488  if (m_currentPacket != 0 && m_currentHdr.IsQosData ()
489  && (m_currentPacketTimestamp + m_queue->GetMaxDelay () < Simulator::Now ()))
490  {
491  NS_LOG_DEBUG ("the lifetime of current packet expired");
492  m_currentPacket = 0;
493  }
494  // If the current packet is a QoS Data frame, then there must be no block ack agreement
495  // established with the receiver for the TID of the packet. Indeed, retransmission
496  // of MPDUs sent under a block ack agreement is handled through the retransmit queue.
499 
500  if (m_currentPacket == 0)
501  {
502  if (m_baManager->HasBar (m_currentBar))
503  {
505  return;
506  }
508  if (peekedItem == 0)
509  {
510  NS_LOG_DEBUG ("no packets available for transmission");
511  return;
512  }
513  // check if a Block Ack agreement needs to be established
514  m_currentHdr = peekedItem->GetHeader ();
515  m_currentPacket = peekedItem->GetPacket ();
518  && (!m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
520  && SetupBlockAckIfNeeded ())
521  {
522  return;
523  }
524 
527  // non-broadcast QoS data frames may be sent in MU PPDUs. Given that at this stage
528  // we do not know the bandwidth it would be given nor the selected acknowledgment
529  // sequence, we cannot determine the constraints on size and duration limit. Hence,
530  // we only peek the non-broadcast QoS data frame. MacLow will be in charge of
531  // computing the correct limits and dequeue the frame.
532  if (peekedItem->GetHeader ().IsQosData () && !peekedItem->GetHeader ().GetAddr1 ().IsBroadcast ()
533  && !NeedFragmentation ())
534  {
535  item = Copy (peekedItem);
536  }
537  else
538  {
539  // compute the limit on the PPDU duration due to the TXOP duration, if any
540  Time ppduDurationLimit = Time::Min ();
541  if (peekedItem->GetHeader ().IsQosData () && GetTxopLimit ().IsStrictlyPositive ())
542  {
544  ppduDurationLimit = GetTxopRemaining () - m_low->CalculateOverheadTxTime (peekedItem, params);
545  }
546 
547  // dequeue the peeked item if it fits within the TXOP duration, if any
548  item = DequeuePeekedFrame (peekedItem, m_low->GetDataTxVector (peekedItem),
549  !NeedFragmentation (), 0, ppduDurationLimit);
550  }
551 
552  if (item == 0)
553  {
554  NS_LOG_DEBUG ("Not enough time in the current TXOP");
555  return;
556  }
557  m_currentPacket = item->GetPacket ();
558  m_currentHdr = item->GetHeader ();
559  m_currentPacketTimestamp = item->GetTimeStamp ();
560  NS_ASSERT (m_currentPacket != 0);
561 
562  m_fragmentNumber = 0;
563  }
564  Ptr<WifiMacQueueItem> mpdu = Create <WifiMacQueueItem> (m_currentPacket, m_currentHdr,
566  if (m_currentHdr.GetAddr1 ().IsGroup ())
567  {
571  NS_LOG_DEBUG ("tx broadcast");
572  m_low->StartTransmission (mpdu, m_currentParams, this);
573  }
575  {
577  }
578  else
579  {
581 
582  //With COMPRESSED_BLOCK_ACK fragmentation must be avoided.
584  || (m_currentHdr.IsData () && !m_currentHdr.IsQosData ()))
586  && NeedFragmentation ())
587  {
588  m_currentIsFragmented = true;
590  WifiMacHeader hdr;
591  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
592  if (IsLastFragment ())
593  {
594  NS_LOG_DEBUG ("fragmenting last fragment size=" << fragment->GetSize ());
596  }
597  else
598  {
599  NS_LOG_DEBUG ("fragmenting size=" << fragment->GetSize ());
601  }
602  m_low->StartTransmission (Create<WifiMacQueueItem> (fragment, hdr),
603  m_currentParams, this);
604  }
605  else
606  {
607  m_currentIsFragmented = false;
608  m_low->StartTransmission (mpdu, m_currentParams, this);
609  }
610  }
611 }
612 
614 {
615  NS_LOG_FUNCTION (this);
616  bool resetDcf = false;
617  // If an internal collision is experienced, the frame involved may still
618  // be sitting in the queue, and m_currentPacket may still be null.
619  Ptr<const Packet> packet;
620  WifiMacHeader header;
621  if (m_currentPacket == 0)
622  {
624  if (item)
625  {
626  packet = item->GetPacket ();
627  header = item->GetHeader ();
628  }
629  }
630  else
631  {
632  packet = m_currentPacket;
633  header = m_currentHdr;
634  }
635  if (packet != 0)
636  {
638  {
639  if (!NeedRtsRetransmission (packet, header))
640  {
641  resetDcf = true;
642  m_stationManager->ReportFinalRtsFailed (header.GetAddr1 (), &header);
643  }
644  else
645  {
646  m_stationManager->ReportRtsFailed (header.GetAddr1 (), &header);
647  }
648  }
649  else if (header.GetAddr1 () == Mac48Address::GetBroadcast ())
650  {
651  resetDcf = false;
652  }
653  else
654  {
655  if (!NeedDataRetransmission (packet, header))
656  {
657  resetDcf = true;
658  m_stationManager->ReportFinalDataFailed (header.GetAddr1 (), &header, packet->GetSize ());
659  }
660  else
661  {
662  m_stationManager->ReportDataFailed (header.GetAddr1 (), &header, packet->GetSize ());
663  }
664  }
665  if (resetDcf)
666  {
667  NS_LOG_DEBUG ("reset DCF");
668  if (!m_txFailedCallback.IsNull ())
669  {
670  m_txFailedCallback (header);
671  }
672  //to reset the dcf.
673  if (m_currentPacket)
674  {
675  NS_LOG_DEBUG ("Discarding m_currentPacket");
676  m_currentPacket = 0;
677  }
678  else
679  {
680  NS_LOG_DEBUG ("Dequeueing and discarding head of queue");
681  m_queue->Remove ();
682  }
683  ResetCw ();
684  }
685  else
686  {
687  UpdateFailedCw ();
688  }
689  }
690  GenerateBackoff ();
692 }
693 
694 void
696 {
697  NS_LOG_FUNCTION (this);
698  NS_LOG_DEBUG ("missed cts");
699  NS_ASSERT (!mpduList.empty ());
701  {
702  NS_LOG_DEBUG ("Cts Fail");
704  if (!m_txFailedCallback.IsNull ())
705  {
707  }
708  for (auto& mpdu : mpduList)
709  {
710  m_baManager->NotifyDiscardedMpdu (mpdu);
711  }
712  //to reset the dcf.
713  m_currentPacket = 0;
714  ResetCw ();
715  m_cwTrace = GetCw ();
716  }
717  else
718  {
719  UpdateFailedCw ();
720  m_cwTrace = GetCw ();
721  // if a BA agreement is established, store the MPDUs in the block ack manager
722  // retransmission queue. Otherwise, this QosTxop will handle the retransmission
723  // of the (single) frame
724  if (mpduList.size () > 1 ||
725  (mpduList.front ()->GetHeader ().IsQosData ()
726  && GetBaAgreementEstablished (mpduList.front ()->GetHeader ().GetAddr1 (),
727  mpduList.front ()->GetHeader ().GetQosTid ())))
728  {
729  for (auto it = mpduList.rbegin (); it != mpduList.rend (); it++)
730  {
731  m_baManager->GetRetransmitQueue ()->PushFront (*it);
732  }
733  m_currentPacket = 0;
734  }
735  }
736  GenerateBackoff ();
738 }
739 
740 void
742 {
743  NS_LOG_FUNCTION (this);
746  || m_currentHdr.IsQosAmsdu ())
747  {
748  NS_LOG_DEBUG ("got ack. tx done.");
749  if (!m_txOkCallback.IsNull ())
750  {
752  }
753 
754  if (m_currentHdr.IsAction ())
755  {
756  WifiActionHeader actionHdr;
758  p->RemoveHeader (actionHdr);
759  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK)
760  {
762  {
763  MgtDelBaHeader delBa;
764  p->PeekHeader (delBa);
765  if (delBa.IsByOriginator ())
766  {
767  m_baManager->DestroyAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
768  }
769  else
770  {
771  m_low->DestroyBlockAckAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
772  }
773  }
775  {
776  // Setup addba response timeout
777  MgtAddBaRequestHeader addBa;
778  p->PeekHeader (addBa);
781  m_currentHdr.GetAddr1 (), addBa.GetTid ());
782  }
783  }
784  }
786  {
787  // notify the BA manager that the current packet was acknowledged
788  m_baManager->NotifyGotAck (Create<const WifiMacQueueItem> (m_currentPacket, m_currentHdr,
790  }
791  m_currentPacket = 0;
792  ResetCw ();
793  }
794  else
795  {
796  NS_LOG_DEBUG ("got ack. tx not done, size=" << m_currentPacket->GetSize ());
797  }
798 }
799 
800 void
802 {
803  NS_LOG_FUNCTION (this);
804  NS_LOG_DEBUG ("missed ack");
806  {
807  NS_LOG_DEBUG ("Ack Fail");
810  if (!m_txFailedCallback.IsNull ())
811  {
813  }
814  if (m_currentHdr.IsAction ())
815  {
816  WifiActionHeader actionHdr;
817  m_currentPacket->PeekHeader (actionHdr);
818  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK)
819  {
820  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
821  if (m_baManager->ExistsAgreementInState (m_currentHdr.GetAddr1 (), tid, OriginatorBlockAckAgreement::PENDING))
822  {
823  NS_LOG_DEBUG ("No ACK after ADDBA request");
824  m_baManager->NotifyAgreementNoReply (m_currentHdr.GetAddr1 (), tid);
826  }
827  }
828  }
830  {
831  m_baManager->NotifyDiscardedMpdu (Create<const WifiMacQueueItem> (m_currentPacket, m_currentHdr));
832  }
833  m_currentPacket = 0;
834  ResetCw ();
835  m_cwTrace = GetCw ();
836  }
837  else
838  {
839  NS_LOG_DEBUG ("Retransmit");
844  {
845  // notify the BA manager that the current packet was not acknowledged
846  m_baManager->NotifyMissedAck (Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr,
848  // let the BA manager handle its retransmission
849  m_currentPacket = 0;
850  }
851  UpdateFailedCw ();
852  m_cwTrace = GetCw ();
853  }
854  GenerateBackoff ();
856 }
857 
858 void
859 QosTxop::MissedBlockAck (uint8_t nMpdus)
860 {
861  NS_LOG_FUNCTION (this << +nMpdus);
862  /*
863  * If the BlockAck frame is lost, the originator may transmit a BlockAckReq
864  * frame to solicit an immediate BlockAck frame or it may retransmit the Data
865  * frames. (IEEE std 802.11-2016 sec. 10.24.7.7
866  */
867  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
869  {
870  if (NeedBarRetransmission ())
871  {
872  NS_LOG_DEBUG ("Retransmit block ack request");
874  {
876  UpdateFailedCw ();
877  m_cwTrace = GetCw ();
878  }
879  else // missed block ack after data frame with Implicit BAR Ack policy
880  {
881  m_baManager->ScheduleBlockAckReq (m_currentHdr.GetAddr1 (), tid);
882  m_currentPacket = 0;
883  }
884  }
885  else
886  {
887  NS_LOG_DEBUG ("Block Ack Request Fail");
888  //to reset the dcf.
889  m_baManager->DiscardOutstandingMpdus (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr));
890  m_currentPacket = 0;
891  ResetCw ();
892  m_cwTrace = GetCw ();
893  }
894  }
895  else
896  {
898  {
899  m_stationManager->ReportAmpduTxStatus (m_currentHdr.GetAddr1 (), tid, 0, nMpdus, 0, 0);
900  }
901  // implicit BAR and do not use BAR after missed block ack, hence try to retransmit data frames
903  {
904  NS_LOG_DEBUG ("Block Ack Fail");
905  if (!m_txFailedCallback.IsNull ())
906  {
908  }
909  if (m_currentHdr.IsAction ())
910  {
911  WifiActionHeader actionHdr;
912  m_currentPacket->PeekHeader (actionHdr);
913  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK)
914  {
915  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
916  if (m_baManager->ExistsAgreementInState (m_currentHdr.GetAddr1 (), tid, OriginatorBlockAckAgreement::PENDING))
917  {
918  NS_LOG_DEBUG ("No ACK after ADDBA request");
919  m_baManager->NotifyAgreementNoReply (m_currentHdr.GetAddr1 (), tid);
921  }
922  }
923  }
924  //to reset the dcf.
925  m_baManager->DiscardOutstandingMpdus (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr));
926  m_currentPacket = 0;
927  ResetCw ();
928  m_cwTrace = GetCw ();
929  }
930  else
931  {
932  NS_LOG_DEBUG ("Retransmit");
933  m_baManager->NotifyMissedBlockAck (m_currentHdr.GetAddr1 (), tid);
934  m_currentPacket = 0;
935  UpdateFailedCw ();
936  m_cwTrace = GetCw ();
937  }
938  }
939  GenerateBackoff ();
941 }
942 
943 void
945 {
946  NS_LOG_FUNCTION (this);
947  if ((m_currentPacket != 0
948  // check first if the BA manager retransmit queue is empty, so that expired
949  // frames (if any) are removed and a Block Ack Request is scheduled to advance
950  // the starting sequence number of the transmit (and receiver) window
951  || m_baManager->HasPackets () || !m_queue->IsEmpty ())
952  && !IsAccessRequested ())
953  {
954  Ptr<const Packet> packet;
955  WifiMacHeader hdr;
956  if (m_currentPacket != 0)
957  {
958  packet = m_currentPacket;
959  hdr = m_currentHdr;
960  }
961  else
962  {
964  if (item)
965  {
966  packet = item->GetPacket ();
967  hdr = item->GetHeader ();
968  }
969  }
970  if (packet != 0)
971  {
973  m_low->GetDataTxVector (Create<const WifiMacQueueItem> (packet, hdr)));
974  }
975  else
976  {
978  }
980  }
981 }
982 
983 void
985 {
986  NS_LOG_FUNCTION (this);
987  if (m_currentPacket == 0
988  // check first if the BA manager retransmit queue is empty, so that expired
989  // frames (if any) are removed and a Block Ack Request is scheduled to advance
990  // the starting sequence number of the transmit (and receiver) window
991  && (m_baManager->HasPackets () || !m_queue->IsEmpty ())
992  && !IsAccessRequested ())
993  {
994  Ptr<const Packet> packet;
995  WifiMacHeader hdr;
997  if (item)
998  {
999  packet = item->GetPacket ();
1000  hdr = item->GetHeader ();
1001  }
1002  if (packet != 0)
1003  {
1005  m_low->GetDataTxVector (Create<const WifiMacQueueItem> (packet, hdr)));
1006  }
1007  else
1008  {
1009  m_isAccessRequestedForRts = false;
1010  }
1012  }
1013 }
1014 
1015 bool
1017 {
1018  uint8_t tid = 0;
1019  if (m_currentHdr.IsQosData ())
1020  {
1021  tid = m_currentHdr.GetQosTid ();
1022  }
1023  else if (m_currentHdr.IsBlockAckReq ())
1024  {
1025  CtrlBAckRequestHeader baReqHdr;
1026  m_currentPacket->PeekHeader (baReqHdr);
1027  tid = baReqHdr.GetTidInfo ();
1028  }
1029  else if (m_currentHdr.IsBlockAck ())
1030  {
1031  CtrlBAckResponseHeader baRespHdr;
1032  m_currentPacket->PeekHeader (baRespHdr);
1033  tid = baRespHdr.GetTidInfo ();
1034  }
1035  return m_baManager->NeedBarRetransmission (tid, m_currentHdr.GetAddr1 ());
1036 }
1037 
1038 void
1040 {
1041  NS_LOG_FUNCTION (this);
1042  NS_ASSERT (GetTxopLimit ().IsStrictlyPositive () && GetTxopRemaining ().IsStrictlyPositive ());
1043 
1044  m_currentPacket = 0;
1045  Ptr<const WifiMacQueueItem> nextFrame;
1046 
1047  // peek the next BlockAckReq, if any
1048  if (m_baManager->HasBar (m_currentBar, false))
1049  {
1050  WifiMacHeader hdr;
1053  nextFrame = Create<const WifiMacQueueItem> (m_currentBar.bar, hdr);
1054  }
1055  else
1056  {
1057  nextFrame = PeekNextFrame ();
1058  }
1059 
1060  if (nextFrame != 0)
1061  {
1063 
1064  if (GetTxopRemaining () >= m_low->CalculateOverallTxTime (nextFrame->GetPacket (), &nextFrame->GetHeader (), params))
1065  {
1066  if (nextFrame->GetHeader ().IsBlockAckReq ())
1067  {
1068  NS_LOG_DEBUG ("start next BlockAckReq within the current TXOP");
1069  m_baManager->HasBar (m_currentBar);
1071  return;
1072  }
1073 
1074  // check if a Block Ack agreement needs to be established
1075  m_currentHdr = nextFrame->GetHeader ();
1076  m_currentPacket = nextFrame->GetPacket ();
1079  && (!m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
1081  && SetupBlockAckIfNeeded ())
1082  {
1083  return;
1084  }
1085 
1086  Ptr<WifiMacQueueItem> item;
1087  // non-broadcast QoS data frames may be sent in MU PPDUs. Given that at this stage
1088  // we do not know the bandwidth it would be given nor the selected acknowledgment
1089  // sequence, we cannot determine the constraints on size and duration limit. Hence,
1090  // we only peek the non-broadcast QoS data frame. MacLow will be in charge of
1091  // computing the correct limits and dequeue the frame.
1092  if (nextFrame->GetHeader ().IsQosData () && !nextFrame->GetHeader ().GetAddr1 ().IsBroadcast ())
1093  {
1094  item = Create<WifiMacQueueItem> (*nextFrame);
1095  }
1096  else
1097  {
1098  // dequeue the peeked frame
1099  item = DequeuePeekedFrame (nextFrame, m_low->GetDataTxVector (nextFrame));
1100  }
1101 
1102  NS_ASSERT (item != 0);
1103  NS_LOG_DEBUG ("start next packet " << *item << " within the current TXOP");
1104  m_currentPacket = item->GetPacket ();
1105  m_currentHdr = item->GetHeader ();
1106  m_currentPacketTimestamp = item->GetTimeStamp ();
1107  NS_ASSERT (m_currentPacket != 0);
1108 
1109  m_currentParams = params;
1111  m_fragmentNumber = 0;
1112  GetLow ()->StartTransmission (item, m_currentParams, this);
1113  return;
1114  }
1115  }
1116 
1117  // terminate TXOP because no (suitable) frame was found
1118  TerminateTxop ();
1119 }
1120 
1121 void
1123 {
1124  NS_LOG_FUNCTION (this);
1125  if (GetTxopLimit ().IsStrictlyPositive ())
1126  {
1127  NS_LOG_DEBUG ("Terminating TXOP. Duration = " << Simulator::Now () - m_startTxop);
1129  }
1130  GenerateBackoff ();
1132 }
1133 
1134 Time
1136 {
1137  Time remainingTxop = GetTxopLimit ();
1138  remainingTxop -= (Simulator::Now () - m_startTxop);
1139  if (remainingTxop.IsStrictlyNegative ())
1140  {
1141  remainingTxop = Seconds (0);
1142  }
1143  NS_LOG_FUNCTION (this << remainingTxop);
1144  return remainingTxop;
1145 }
1146 
1147 void
1149 {
1150  NS_LOG_FUNCTION (this);
1151  NS_LOG_DEBUG ("a transmission that did not require an ACK just finished");
1152  m_currentPacket = 0;
1153  ResetCw ();
1154  TerminateTxop ();
1155 }
1156 
1157 bool
1159 {
1160  NS_LOG_FUNCTION (this);
1165  && m_currentHdr.IsQosData ()
1167  && GetLow ()->GetMpduAggregator () != 0
1168  && GetLow ()->GetMpduAggregator ()->GetMaxAmpduSize (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr),
1170  {
1171  //MSDU is not fragmented when it is transmitted using an HT-immediate or
1172  //HT-delayed Block Ack agreement or when it is carried in an A-MPDU.
1173  return false;
1174  }
1175  bool needTxopFragmentation = false;
1177  {
1178  needTxopFragmentation = (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams) > GetTxopLimit ());
1179  }
1180  return (needTxopFragmentation || m_stationManager->NeedFragmentation (m_currentHdr.GetAddr1 (), &m_currentHdr, m_currentPacket));
1181 }
1182 
1183 bool
1185 {
1186  if (GetTxopLimit ().IsZero ())
1187  {
1188  return false;
1189  }
1192  {
1193  return true;
1194  }
1195  return false;
1196 }
1197 
1198 uint32_t
1200 {
1201  Time txopDuration = GetTxopLimit ();
1202  if (txopDuration.IsZero ())
1203  {
1204  return 0;
1205  }
1206  uint32_t maxSize = m_currentPacket->GetSize ();
1207  uint32_t minSize = 0;
1208  uint32_t size = 0;
1209  bool found = false;
1210  while (!found)
1211  {
1212  size = (minSize + ((maxSize - minSize) / 2));
1213  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) > txopDuration)
1214  {
1215  maxSize = size;
1216  }
1217  else
1218  {
1219  minSize = size;
1220  }
1221  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) <= txopDuration
1222  && GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size + 1) > txopDuration)
1223  {
1224  found = true;
1225  }
1226  }
1227  NS_ASSERT (size != 0);
1228  return size;
1229 }
1230 
1231 uint32_t
1233 {
1234  uint32_t fragmentSize = GetTxopFragmentSize ();
1235  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1236  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1237  {
1238  nFragments++;
1239  }
1240  NS_LOG_DEBUG ("GetNTxopFragment returning " << nFragments);
1241  return nFragments;
1242 }
1243 
1244 uint32_t
1245 QosTxop::GetTxopFragmentOffset (uint32_t fragmentNumber) const
1246 {
1247  if (fragmentNumber == 0)
1248  {
1249  return 0;
1250  }
1251  uint32_t offset = 0;
1252  uint32_t fragmentSize = GetTxopFragmentSize ();
1253  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1254  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1255  {
1256  nFragments++;
1257  }
1258  if (fragmentNumber < nFragments)
1259  {
1260  offset = (fragmentNumber * fragmentSize);
1261  }
1262  else
1263  {
1264  NS_ASSERT (false);
1265  }
1266  NS_LOG_DEBUG ("GetTxopFragmentOffset returning " << offset);
1267  return offset;
1268 }
1269 
1270 uint32_t
1271 QosTxop::GetNextTxopFragmentSize (uint32_t fragmentNumber) const
1272 {
1273  NS_LOG_FUNCTION (this << fragmentNumber);
1274  uint32_t fragmentSize = GetTxopFragmentSize ();
1275  uint32_t nFragments = GetNTxopFragment ();
1276  if (fragmentNumber >= nFragments)
1277  {
1278  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning 0");
1279  return 0;
1280  }
1281  if (fragmentNumber == nFragments - 1)
1282  {
1283  fragmentSize = (m_currentPacket->GetSize () - ((nFragments - 1) * fragmentSize));
1284  }
1285  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning " << fragmentSize);
1286  return fragmentSize;
1287 }
1288 
1289 uint32_t
1291 {
1292  uint32_t size;
1293  if (IsTxopFragmentation ())
1294  {
1296  }
1297  else
1298  {
1300  }
1301  return size;
1302 }
1303 
1304 uint32_t
1306 {
1307  uint32_t size;
1308  if (IsTxopFragmentation ())
1309  {
1311  }
1312  else
1313  {
1315  }
1316  return size;
1317 }
1318 
1319 uint32_t
1321 {
1322  uint32_t offset;
1323  if (IsTxopFragmentation ())
1324  {
1326  }
1327  else
1328  {
1331  }
1332  return offset;
1333 }
1334 
1335 bool
1337 {
1338  bool isLastFragment;
1339  if (IsTxopFragmentation ())
1340  {
1341  isLastFragment = (m_fragmentNumber == GetNTxopFragment () - 1);
1342  }
1343  else
1344  {
1347  }
1348  return isLastFragment;
1349 }
1350 
1353 {
1354  NS_LOG_FUNCTION (this << hdr);
1355  *hdr = m_currentHdr;
1357  uint32_t startOffset = GetFragmentOffset ();
1358  Ptr<Packet> fragment;
1359  if (IsLastFragment ())
1360  {
1361  hdr->SetNoMoreFragments ();
1362  }
1363  else
1364  {
1365  hdr->SetMoreFragments ();
1366  }
1367  fragment = m_currentPacket->CreateFragment (startOffset,
1368  GetFragmentSize ());
1369  return fragment;
1370 }
1371 
1372 void
1374 {
1375  NS_LOG_FUNCTION (this << +ac);
1376  m_ac = ac;
1377 }
1378 
1381 {
1382  NS_LOG_FUNCTION (this << &hdr);
1383  Mac48Address retval;
1384  if (GetTypeOfStation () == STA || GetTypeOfStation () == ADHOC_STA)
1385  {
1386  retval = hdr.GetAddr2 ();
1387  }
1388  else
1389  {
1390  retval = hdr.GetAddr3 ();
1391  }
1392  return retval;
1393 }
1394 
1397 {
1398  NS_LOG_FUNCTION (this << &hdr);
1399  Mac48Address retval;
1400  if (GetTypeOfStation () == AP || GetTypeOfStation () == ADHOC_STA)
1401  {
1402  retval = hdr.GetAddr1 ();
1403  }
1404  else
1405  {
1406  retval = hdr.GetAddr3 ();
1407  }
1408  return retval;
1409 }
1410 
1411 void
1413 {
1414  NS_LOG_FUNCTION (this << packet << &hdr);
1415  WifiMacTrailer fcs;
1416  m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr, packet);
1417  m_queue->PushFront (Create<WifiMacQueueItem> (packet, hdr));
1419 }
1420 
1421 void
1423 {
1424  NS_LOG_FUNCTION (this << respHdr << recipient);
1425  uint8_t tid = respHdr->GetTid ();
1426  if (respHdr->GetStatusCode ().IsSuccess ())
1427  {
1428  NS_LOG_DEBUG ("block ack agreement established with " << recipient);
1429  // Even though a (destination, TID) pair is "blocked" (i.e., no more packets
1430  // are sent) when an Add BA Request is sent to the destination,
1431  // the current packet may still be non-null when the Add BA Response is received.
1432  // In fact, if the Add BA Request timer expires, the (destination, TID) pair is
1433  // "unblocked" and packets to the destination are sent again (under normal
1434  // ack policy). Thus, there may be a packet needing to be retransmitted
1435  // when the Add BA Response is received. If this is the case, let the Block
1436  // Ack manager handle its retransmission.
1437  if (m_currentPacket != 0 && m_currentHdr.IsQosData ()
1438  && m_currentHdr.GetAddr1 () == recipient && m_currentHdr.GetQosTid () == tid)
1439  {
1440  Ptr<WifiMacQueueItem> mpdu = Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr,
1442  m_baManager->GetRetransmitQueue ()->Enqueue (mpdu);
1443  m_currentPacket = 0;
1444  }
1445  m_baManager->UpdateAgreement (respHdr, recipient);
1446  }
1447  else
1448  {
1449  NS_LOG_DEBUG ("discard ADDBA response" << recipient);
1450  m_baManager->NotifyAgreementRejected (recipient, tid);
1451  }
1453 }
1454 
1455 void
1457 {
1458  NS_LOG_FUNCTION (this << delBaHdr << recipient);
1459  NS_LOG_DEBUG ("received DELBA frame from=" << recipient);
1460  m_baManager->DestroyAgreement (recipient, delBaHdr->GetTid ());
1461 }
1462 
1463 void
1464 QosTxop::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, WifiMode txMode, double dataSnr)
1465 {
1466  NS_LOG_FUNCTION (this << blockAck << recipient << rxSnr << txMode.GetUniqueName () << dataSnr);
1467  NS_LOG_DEBUG ("got block ack from=" << recipient);
1468  m_baManager->NotifyGotBlockAck (blockAck, recipient, rxSnr, txMode, dataSnr);
1469  if (!m_txOkCallback.IsNull ())
1470  {
1472  }
1473  m_currentPacket = 0;
1474  ResetCw ();
1475 }
1476 
1478 {
1479  NS_LOG_FUNCTION (this << dest);
1480  auto it = m_aMpduEnabled.find (dest);
1481  if (it != m_aMpduEnabled.end ())
1482  {
1483  return it->second;
1484  }
1485  return false;
1486 }
1487 
1488 void QosTxop::SetAmpduExist (Mac48Address dest, bool enableAmpdu)
1489 {
1490  NS_LOG_FUNCTION (this << dest << enableAmpdu);
1491  m_aMpduEnabled[dest] = enableAmpdu;
1492 }
1493 
1494 void
1496 {
1497  NS_ASSERT (mpdu->GetHeader ().IsQosData ());
1498  // If there is an established BA agreement, store the packet in the queue of outstanding packets
1499  if (GetBaAgreementEstablished (mpdu->GetHeader ().GetAddr1 (), mpdu->GetHeader ().GetQosTid ()))
1500  {
1501  m_baManager->StorePacket (mpdu);
1502  }
1503 }
1504 
1505 bool
1507 {
1508  NS_LOG_FUNCTION (this);
1509  uint8_t tid = m_currentHdr.GetQosTid ();
1510  Mac48Address recipient = m_currentHdr.GetAddr1 ();
1511  uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, recipient);
1512  if ((GetBlockAckThreshold () > 0 && packets >= GetBlockAckThreshold ())
1513  || (GetLow ()->GetMpduAggregator () != 0 && GetLow ()->GetMpduAggregator ()->GetMaxAmpduSize (recipient, tid, WIFI_MOD_CLASS_HT) > 0 && packets > 1)
1516  {
1517  /* Block ack setup */
1518  uint16_t startingSequence = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
1519  SendAddBaRequest (recipient, tid, startingSequence, m_blockAckInactivityTimeout, true);
1520  return true;
1521  }
1522  return false;
1523 }
1524 
1525 void
1527 {
1528  NS_LOG_FUNCTION (this << &bar);
1529  WifiMacHeader hdr;
1531  hdr.SetAddr1 (bar.recipient);
1532  hdr.SetAddr2 (m_low->GetAddress ());
1533  hdr.SetDsNotTo ();
1534  hdr.SetDsNotFrom ();
1535  hdr.SetNoRetry ();
1536  hdr.SetNoMoreFragments ();
1537 
1538  m_currentPacket = bar.bar;
1539  m_currentHdr = hdr;
1540 
1541  Ptr<WifiMacQueueItem> mpdu = Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr);
1543 
1544  m_low->StartTransmission (mpdu, m_currentParams, this);
1545 }
1546 
1547 void
1549 {
1550  NS_LOG_FUNCTION (this);
1551  m_baManager->SetTxMiddle (m_txMiddle);
1552  m_low->RegisterEdcaForAc (m_ac, this);
1553  m_baManager->SetBlockAckInactivityCallback (MakeCallback (&QosTxop::SendDelbaFrame, this));
1554 }
1555 
1556 void
1558 {
1559  NS_LOG_FUNCTION (this << +threshold);
1560  m_blockAckThreshold = threshold;
1561  m_baManager->SetBlockAckThreshold (threshold);
1562 }
1563 
1564 void
1566 {
1567  NS_LOG_FUNCTION (this << timeout);
1569 }
1570 
1571 uint8_t
1573 {
1574  NS_LOG_FUNCTION (this);
1575  return m_blockAckThreshold;
1576 }
1577 
1578 void
1579 QosTxop::SendAddBaRequest (Mac48Address dest, uint8_t tid, uint16_t startSeq,
1580  uint16_t timeout, bool immediateBAck)
1581 {
1582  NS_LOG_FUNCTION (this << dest << +tid << startSeq << timeout << immediateBAck);
1583  NS_LOG_DEBUG ("sent ADDBA request to " << dest);
1584  WifiMacHeader hdr;
1586  hdr.SetAddr1 (dest);
1587  hdr.SetAddr2 (m_low->GetAddress ());
1588  hdr.SetAddr3 (m_low->GetBssid ());
1589  hdr.SetDsNotTo ();
1590  hdr.SetDsNotFrom ();
1591 
1592  WifiActionHeader actionHdr;
1595  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1596 
1597  Ptr<Packet> packet = Create<Packet> ();
1598  /*Setting ADDBARequest header*/
1599  MgtAddBaRequestHeader reqHdr;
1600  reqHdr.SetAmsduSupport (true);
1601  if (immediateBAck)
1602  {
1603  reqHdr.SetImmediateBlockAck ();
1604  }
1605  else
1606  {
1607  reqHdr.SetDelayedBlockAck ();
1608  }
1609  reqHdr.SetTid (tid);
1610  /* For now we don't use buffer size field in the ADDBA request frame. The recipient
1611  * will choose how many packets it can receive under block ack.
1612  */
1613  reqHdr.SetBufferSize (0);
1614  reqHdr.SetTimeout (timeout);
1615  reqHdr.SetStartingSequence (startSeq);
1616 
1617  m_baManager->CreateAgreement (&reqHdr, dest);
1618 
1619  packet->AddHeader (reqHdr);
1620  packet->AddHeader (actionHdr);
1621 
1622  m_currentPacket = packet;
1623  m_currentHdr = hdr;
1624 
1625  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
1626  m_currentHdr.SetSequenceNumber (sequence);
1631 
1635 
1636  m_low->StartTransmission (Create<WifiMacQueueItem> (m_currentPacket, m_currentHdr), m_currentParams, this);
1637 }
1638 
1639 void
1640 QosTxop::SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator)
1641 {
1642  NS_LOG_FUNCTION (this << addr << +tid << byOriginator);
1643  WifiMacHeader hdr;
1645  hdr.SetAddr1 (addr);
1646  hdr.SetAddr2 (m_low->GetAddress ());
1647  hdr.SetAddr3 (m_low->GetBssid ());
1648  hdr.SetDsNotTo ();
1649  hdr.SetDsNotFrom ();
1650 
1651  MgtDelBaHeader delbaHdr;
1652  delbaHdr.SetTid (tid);
1653  if (byOriginator)
1654  {
1655  delbaHdr.SetByOriginator ();
1656  m_baManager->DestroyAgreement (addr, tid);
1657  }
1658  else
1659  {
1660  delbaHdr.SetByRecipient ();
1661  m_low->DestroyBlockAckAgreement (addr, tid);
1662  }
1663 
1664  WifiActionHeader actionHdr;
1667  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1668 
1669  Ptr<Packet> packet = Create<Packet> ();
1670  packet->AddHeader (delbaHdr);
1671  packet->AddHeader (actionHdr);
1672 
1673  PushFront (packet, hdr);
1674 }
1675 
1676 void
1678 {
1679  NS_LOG_FUNCTION (this);
1680  ResetCw ();
1681  m_cwTrace = GetCw ();
1682  GenerateBackoff ();
1683 }
1684 
1685 void
1687 {
1688  NS_LOG_FUNCTION (this << hdr);
1689  if (!m_txOkCallback.IsNull ())
1690  {
1692  }
1693 }
1694 
1695 void
1697 {
1698  NS_LOG_FUNCTION (this << hdr);
1699  if (!m_txFailedCallback.IsNull ())
1700  {
1702  }
1703 }
1704 
1705 void
1707 {
1708  NS_LOG_FUNCTION (this << recipient << +tid);
1709  // If agreement is still pending, ADDBA response is not received
1710  if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::PENDING))
1711  {
1712  m_baManager->NotifyAgreementNoReply (recipient, tid);
1713  Simulator::Schedule (m_failedAddBaTimeout, &QosTxop::ResetBa, this, recipient, tid);
1714  GenerateBackoff ();
1716  }
1717 }
1718 
1719 void
1720 QosTxop::ResetBa (Mac48Address recipient, uint8_t tid)
1721 {
1722  NS_LOG_FUNCTION (this << recipient << +tid);
1723  // This function is scheduled when waiting for an ADDBA response. However,
1724  // before this function is called, a DELBA request may arrive, which causes
1725  // the agreement to be deleted. Hence, check if an agreement exists before
1726  // notifying that the agreement has to be reset.
1727  if (m_baManager->ExistsAgreement (recipient, tid)
1728  && !m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED))
1729  {
1730  m_baManager->NotifyAgreementReset (recipient, tid);
1731  }
1732 }
1733 
1734 void
1736 {
1737  NS_LOG_FUNCTION (this << addBaResponseTimeout);
1738  m_addBaResponseTimeout = addBaResponseTimeout;
1739 }
1740 
1741 Time
1743 {
1744  return m_addBaResponseTimeout;
1745 }
1746 
1747 void
1749 {
1750  NS_LOG_FUNCTION (this << failedAddBaTimeout);
1751  m_failedAddBaTimeout = failedAddBaTimeout;
1752 }
1753 
1754 Time
1756 {
1757  return m_failedAddBaTimeout;
1758 }
1759 
1760 bool
1762 {
1763  return true;
1764 }
1765 
1766 } //namespace ns3
void ScheduleBlockAckReq(Mac48Address address, uint8_t tid)
Definition: qos-txop.cc:146
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:626
TxFailed m_txFailedCallback
the transmit failed callback
Definition: txop.h:507
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:801
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:232
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:1135
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:1477
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:1720
AttributeValue implementation for Boolean.
Definition: boolean.h:36
void RestartAccessIfNeeded(void)
Restart access request if needed.
Definition: qos-txop.cc:944
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 Block ACK type
Definition: qos-txop.h:632
#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.
Definition: nstime.h:268
Time m_startTxop
the start TXOP time
Definition: qos-txop.h:636
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:1396
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
bool m_isAccessRequestedForRts
flag whether access is requested to transmit a RTS frame
Definition: qos-txop.h:637
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 Block ACK timeout has occurred.
Definition: qos-txop.cc:859
Implement the header for management frames of type add block ack request.
Definition: mgt-headers.h:1003
bool NeedBarRetransmission(void)
Check if Block ACK Request should be re-transmitted.
Definition: qos-txop.cc:1016
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:204
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1070
void SetBlockAckInactivityTimeout(uint16_t timeout)
Set the Block Ack inactivity timeout.
Definition: qos-txop.cc:1565
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:1640
Ptr< WifiAckPolicySelector > GetAckPolicySelector(void) const
Return the ack policy selector.
Definition: qos-txop.cc:167
#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:140
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:1456
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)
CategoryValue GetCategory()
Return the category value.
virtual ~QosTxop()
Definition: qos-txop.cc:112
void PrepareForQueue(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
ns3::Time timeout
virtual void GenerateBackoff(void)
Generate a new backoff now.
Definition: txop.cc:558
void SetAccessCategory(AcIndex ac)
Set the access category of this EDCAF.
Definition: qos-txop.cc:1373
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:1572
Block Ack Request.
void DoDispose(void)
Destructor implementation.
Definition: qos-txop.cc:118
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:1199
Time m_failedAddBaTimeout
timeout after failed BA agreement
Definition: qos-txop.h:640
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:1336
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:1320
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:1742
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:1305
void SetAmpduExist(Mac48Address dest, bool enableAmpdu)
Set indication whether A-MPDU is used to transmit data to a peer station.
Definition: qos-txop.cc:1488
void StartAccessIfNeeded(void)
Request access from DCF manager if needed.
Definition: qos-txop.cc:984
void SetFailedAddBaTimeout(Time failedAddBaTimeout)
Set the timeout for failed BA agreement.
Definition: qos-txop.cc:1748
void SendBlockAckRequest(const Bar &bar)
After that all packets, for which a block ack agreement was established, have been transmitted...
Definition: qos-txop.cc:1526
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:630
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:1422
void SetTypeOfStation(TypeOfStation type)
Set type of station with the given type.
Definition: qos-txop.cc:173
static const ConstIterator EMPTY
Invalid iterator to signal an empty queue.
virtual bool IsAccessRequested(void) const
Definition: txop.cc:464
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:1290
uint16_t GetNextSequenceNumberFor(const WifiMacHeader *hdr)
Return the next sequence number for the given header.
Definition: qos-txop.cc:194
void PushFront(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Definition: qos-txop.cc:1412
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:200
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
bool IsQosTxop(void) const
Check for QoS TXOP.
Definition: qos-txop.cc:1761
uint32_t GetNTxopFragment(void) const
Calculate the number of TXOP fragments needed for the transmission of the current packet...
Definition: qos-txop.cc:1232
Mac48Address recipient
recipient
void SetAddBaResponseTimeout(Time addBaResponseTimeout)
Set the timeout to wait for ADDBA response.
Definition: qos-txop.cc:1735
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:382
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:367
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t GetCw(void) const
Definition: txop.cc:211
Hold objects of type Ptr<T>.
Definition: pointer.h:36
bool IsData(void) const
Return true if the Type is DATA.
address
Definition: first.py:44
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:1696
Bar m_currentBar
the current BAR
Definition: qos-txop.h:635
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:695
void CompleteMpduTx(Ptr< WifiMacQueueItem > mpdu)
Stores an MPDU (part of an A-MPDU) in blockackagreement (i.e.
Definition: qos-txop.cc:1495
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:107
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:225
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:396
bool NeedDataRetransmission(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Check if DATA should be re-transmitted if ACK was missed.
Definition: txop.cc:389
void BaTxOk(const WifiMacHeader &hdr)
The packet we sent was successfully received by the receiver.
Definition: qos-txop.cc:1686
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: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:1148
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:1557
void UpdateCurrentPacket(Ptr< WifiMacQueueItem > mpdu)
Update the current packet this QosTxop is trying to transmit.
Definition: qos-txop.cc:471
Ptr< MacLow > m_low
the MacLow
Definition: txop.h:511
uint8_t m_blockAckThreshold
the Block ACK threshold
Definition: qos-txop.h:631
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > remoteManager)
Set WifiRemoteStationsManager this QosTxop is associated to.
Definition: qos-txop.cc:152
uint32_t GetTxopFragmentOffset(uint32_t fragmentNumber) const
Calculate the offset for the fragment.
Definition: qos-txop.cc:1245
Ptr< WifiAckPolicySelector > m_ackPolicySelector
Ack policy selector.
Definition: qos-txop.h:628
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:297
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:206
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 EDCAF has frames to transmit.
Definition: qos-txop.cc:186
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:1464
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:741
void StartNextPacket(void)
Start transmission for the next packet if allowed by the TxopLimit.
Definition: qos-txop.cc:1039
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
Definition: nstime.h:303
Implement the header for management frames of type del 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:1380
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:272
bool m_useExplicitBarAfterMissedBlockAck
flag whether explicit Block Ack Request should be sent upon missed Block Ack Response ...
Definition: qos-txop.h:641
TypeOfStation GetTypeOfStation(void) const
Return type of station.
Definition: qos-txop.cc:180
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:1062
Ptr< const Packet > bar
block ack request
Ptr< QosBlockedDestinations > m_qosBlockedDestinations
QOS blocked destinations.
Definition: qos-txop.h:629
void NotifyAccessGranted(void)
Notify the EDCAF that access has been granted.
Definition: qos-txop.cc:480
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.
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:1548
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:638
void SetAckPolicySelector(Ptr< WifiAckPolicySelector > ackSelector)
Set the ack policy selector.
Definition: qos-txop.cc:160
bool IsAction() const
Return true if the header is an Action header.
uint8_t m_fragmentNumber
the fragment number
Definition: txop.h:534
TracedCallback< Time, Time > m_txopTrace
TXOP trace callback.
Definition: qos-txop.h:643
void DoInitialize(void)
Initialize() implementation.
Definition: qos-txop.cc:1677
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:1122
bool NeedFragmentation(void) const
Check if the current packet should be fragmented.
Definition: qos-txop.cc:1158
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:633
bool IsTxopFragmentation(void) const
Check if the current packet is fragmented because of an exceeded TXOP duration.
Definition: qos-txop.cc:1184
void EnableBlockAck(BlockAckType type)
Wait the timeout corresponding to the given Block Ack 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:1352
Time GetFailedAddBaTimeout(void) const
Get the timeout for failed BA agreement.
Definition: qos-txop.cc:1755
ActionValue GetAction()
Return the action value.
uint16_t m_blockAckInactivityTimeout
the Block ACK inactivity timeout
Definition: qos-txop.h:634
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: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:1506
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:613
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:1271
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
TypeOfStation m_typeOfStation
the type of station
Definition: qos-txop.h:627
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
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:688
void AddBaResponseTimeout(Mac48Address recipient, uint8_t tid)
Callback when ADDBA response is not received after timeout.
Definition: qos-txop.cc:1706
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:639
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:1579
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