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  */
22 
23 #include "ns3/log.h"
24 #include "ns3/simulator.h"
25 #include "ns3/random-variable-stream.h"
26 #include "qos-txop.h"
27 #include "channel-access-manager.h"
28 #include "mac-tx-middle.h"
29 #include "mgt-headers.h"
30 #include "wifi-mac-trailer.h"
31 #include "wifi-mac-queue.h"
32 #include "mac-low.h"
35 #include "msdu-aggregator.h"
36 #include "mpdu-aggregator.h"
37 #include "ctrl-headers.h"
38 
39 #undef NS_LOG_APPEND_CONTEXT
40 #define NS_LOG_APPEND_CONTEXT if (m_low != 0) { std::clog << "[mac=" << m_low->GetAddress () << "] "; }
41 
42 namespace ns3 {
43 
44 NS_LOG_COMPONENT_DEFINE ("QosTxop");
45 
47 
48 TypeId
50 {
51  static TypeId tid = TypeId ("ns3::QosTxop")
52  .SetParent<ns3::Txop> ()
53  .SetGroupName ("Wifi")
54  .AddConstructor<QosTxop> ()
55  .AddTraceSource ("BackoffTrace",
56  "Trace source for backoff values",
58  "ns3::TracedValueCallback::Uint32")
59  .AddTraceSource ("CwTrace",
60  "Trace source for contention window values",
62  "ns3::TracedValueCallback::Uint32")
63  .AddTraceSource ("TxopTrace",
64  "Trace source for txop start and duration times",
66  "ns3::TracedValueCallback::Time")
67  ;
68  return tid;
69 }
70 
72  : m_msduAggregator (0),
73  m_mpduAggregator (0),
74  m_typeOfStation (STA),
75  m_blockAckType (COMPRESSED_BLOCK_ACK),
76  m_startTxop (Seconds (0)),
77  m_isAccessRequestedForRts (false),
78  m_currentIsFragmented (false)
79 {
80  NS_LOG_FUNCTION (this);
81  m_qosBlockedDestinations = Create<QosBlockedDestinations> ();
82  m_baManager = CreateObject<BlockAckManager> ();
83  m_baManager->SetQueue (m_queue);
84  m_baManager->SetBlockAckType (m_blockAckType);
87  m_baManager->SetMaxPacketDelay (m_queue->GetMaxDelay ());
88  m_baManager->SetTxOkCallback (MakeCallback (&QosTxop::BaTxOk, this));
89  m_baManager->SetTxFailedCallback (MakeCallback (&QosTxop::BaTxFailed, this));
90 }
91 
93 {
94  NS_LOG_FUNCTION (this);
95 }
96 
97 void
99 {
100  NS_LOG_FUNCTION (this);
101  m_baManager = 0;
103  m_msduAggregator = 0;
104  m_mpduAggregator = 0;
105  Txop::DoDispose ();
106 }
107 
108 bool
110 {
111  return m_baManager->ExistsAgreement (address, tid);
112 }
113 
114 void
116 {
117  m_baManager->CompleteAmpduExchange (recipient, tid);
118 }
119 
120 void
122 {
123  Txop::SetWifiRemoteStationManager (remoteManager);
124  NS_LOG_FUNCTION (this << remoteManager);
125  m_baManager->SetWifiRemoteStationManager (m_stationManager);
126 }
127 
128 void
130 {
131  NS_LOG_FUNCTION (this << +type);
132  m_typeOfStation = type;
133 }
134 
137 {
138  return m_typeOfStation;
139 }
140 
141 uint16_t
143 {
144  return m_txMiddle->GetNextSequenceNumberFor (hdr);
145 }
146 
147 uint16_t
149 {
151 }
152 
154 QosTxop::PeekNextRetransmitPacket (WifiMacHeader &header, uint8_t tid, Time *timestamp)
155 {
156  return m_baManager->PeekNextPacketByTidAndAddress (header, tid, timestamp);
157 }
158 
159 void
160 QosTxop::RemoveRetransmitPacket (uint8_t tid, Mac48Address recipient, uint16_t seqnumber)
161 {
162  m_baManager->RemovePacket (tid, recipient, seqnumber);
163 }
164 
165 void
167 {
168  NS_LOG_FUNCTION (this);
170  m_accessRequested = false;
173  if (m_currentPacket == 0)
174  {
175  if (m_queue->IsEmpty () && !m_baManager->HasPackets ())
176  {
177  NS_LOG_DEBUG ("queue is empty");
178  return;
179  }
180  if (m_baManager->HasBar (m_currentBar))
181  {
183  return;
184  }
185  /* check if packets need retransmission are stored in BlockAckManager */
186  m_currentPacket = m_baManager->GetNextPacket (m_currentHdr, true);
187  if (m_currentPacket == 0)
188  {
189  Ptr<const WifiMacQueueItem> item = m_queue->PeekFirstAvailable (m_qosBlockedDestinations);
190  if (item == 0)
191  {
192  NS_LOG_DEBUG ("no available packets in the queue");
193  return;
194  }
195  m_currentHdr = item->GetHeader ();
196  m_currentPacketTimestamp = item->GetTimeStamp ();
199  && !m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
200  && SetupBlockAckIfNeeded ())
201  {
202  return;
203  }
204  item = m_queue->DequeueFirstAvailable (m_qosBlockedDestinations);
205  m_currentPacket = item->GetPacket ();
206  m_currentHdr = item->GetHeader ();
207  m_currentPacketTimestamp = item->GetTimeStamp ();
208  NS_ASSERT (m_currentPacket != 0);
209 
210  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
211  m_currentHdr.SetSequenceNumber (sequence);
216  m_fragmentNumber = 0;
217  NS_LOG_DEBUG ("dequeued size=" << m_currentPacket->GetSize () <<
218  ", to=" << m_currentHdr.GetAddr1 () <<
219  ", seq=" << m_currentHdr.GetSequenceControl ());
221  {
222  VerifyBlockAck ();
223  }
224  }
225  }
226  if (m_currentHdr.GetAddr1 ().IsGroup ())
227  {
231  NS_LOG_DEBUG ("tx broadcast");
233  }
235  {
237  }
238  else
239  {
241  {
243  }
244  else
245  {
247  }
248  //With COMPRESSED_BLOCK_ACK fragmentation must be avoided.
250  || (m_currentHdr.IsData () && !m_currentHdr.IsQosData ()))
252  && NeedFragmentation ())
253  {
254  m_currentIsFragmented = true;
256  WifiMacHeader hdr;
257  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
258  if (IsLastFragment ())
259  {
260  NS_LOG_DEBUG ("fragmenting last fragment size=" << fragment->GetSize ());
262  }
263  else
264  {
265  NS_LOG_DEBUG ("fragmenting size=" << fragment->GetSize ());
267  }
268  m_low->StartTransmission (fragment, &hdr, m_currentParams, this);
269  }
270  else
271  {
272  m_currentIsFragmented = false;
273  WifiMacHeader peekedHdr;
275  if (m_currentHdr.IsQosData ()
276  && (item = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
279  && m_msduAggregator != 0 && !m_currentHdr.IsRetry ())
280  {
281  peekedHdr = item->GetHeader ();
282  /* here is performed aggregation */
283  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
284  m_msduAggregator->Aggregate (m_currentPacket, currentAggregatedPacket,
285  MapSrcAddressForAggregation (peekedHdr),
286  MapDestAddressForAggregation (peekedHdr));
287  bool aggregated = false;
288  bool isAmsdu = false;
289  Ptr<const WifiMacQueueItem> peekedItem = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
291  while (peekedItem != 0)
292  {
293  peekedHdr = peekedItem->GetHeader ();
294  aggregated = m_msduAggregator->Aggregate (peekedItem->GetPacket (), currentAggregatedPacket,
295  MapSrcAddressForAggregation (peekedHdr),
296  MapDestAddressForAggregation (peekedHdr));
297  if (aggregated)
298  {
299  isAmsdu = true;
300  m_queue->Remove (peekedItem->GetPacket ());
301  }
302  else
303  {
304  break;
305  }
306  peekedItem = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
308  }
309  if (isAmsdu)
310  {
313  m_currentPacket = currentAggregatedPacket;
314  currentAggregatedPacket = 0;
315  NS_LOG_DEBUG ("tx unicast A-MSDU");
316  }
317  }
321  {
322  CompleteTx ();
323  }
324  }
325  }
326 }
327 
329 {
330  NS_LOG_FUNCTION (this);
331  bool resetDcf = false;
332  // If an internal collision is experienced, the frame involved may still
333  // be sitting in the queue, and m_currentPacket may still be null.
334  Ptr<const Packet> packet;
335  WifiMacHeader header;
336  if (m_currentPacket == 0)
337  {
338  if (m_baManager->HasPackets ())
339  {
340  packet = m_baManager->GetNextPacket (header, false);
341  }
342  else
343  {
344  Ptr<const WifiMacQueueItem> item = m_queue->Peek ();
345  if (item)
346  {
347  packet = item->GetPacket ();
348  header = item->GetHeader ();
349  }
350  }
351  }
352  else
353  {
354  packet = m_currentPacket;
355  header = m_currentHdr;
356  }
357  if (packet != 0)
358  {
360  {
361  if (!NeedRtsRetransmission (packet, header))
362  {
363  resetDcf = true;
364  m_stationManager->ReportFinalRtsFailed (header.GetAddr1 (), &header);
365  }
366  else
367  {
368  m_stationManager->ReportRtsFailed (header.GetAddr1 (), &header);
369  }
370  }
371  else if (header.GetAddr1 () == Mac48Address::GetBroadcast ())
372  {
373  resetDcf = false;
374  }
375  else
376  {
377  if (!NeedDataRetransmission (packet, header))
378  {
379  resetDcf = true;
380  m_stationManager->ReportFinalDataFailed (header.GetAddr1 (), &header, packet->GetSize ());
381  }
382  else
383  {
384  m_stationManager->ReportDataFailed (header.GetAddr1 (), &header, packet->GetSize ());
385  }
386  }
387  if (resetDcf)
388  {
389  NS_LOG_DEBUG ("reset DCF");
390  if (!m_txFailedCallback.IsNull ())
391  {
392  m_txFailedCallback (header);
393  }
394  //to reset the dcf.
395  if (m_currentPacket)
396  {
397  NS_LOG_DEBUG ("Discarding m_currentPacket");
398  m_currentPacket = 0;
399  }
400  else
401  {
402  NS_LOG_DEBUG ("Dequeueing and discarding head of queue");
403  m_queue->Remove ();
404  }
405  ResetCw ();
406  }
407  else
408  {
409  UpdateFailedCw ();
410  }
411  }
415 }
416 
417 void
419 {
420  NS_LOG_FUNCTION (this);
424 }
425 
426 void
428 {
429  NS_LOG_FUNCTION (this);
430  NS_LOG_DEBUG ("missed cts");
432  {
433  NS_LOG_DEBUG ("Cts Fail");
434  bool resetCurrentPacket = true;
436  if (!m_txFailedCallback.IsNull ())
437  {
439  }
441  {
442  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
443  m_low->FlushAggregateQueue (tid);
444 
446  {
447  NS_LOG_DEBUG ("Transmit Block Ack Request");
448  CtrlBAckRequestHeader reqHdr;
449  reqHdr.SetType (COMPRESSED_BLOCK_ACK);
451  reqHdr.SetTidInfo (tid);
452  reqHdr.SetHtImmediateAck (true);
453  Ptr<Packet> bar = Create<Packet> ();
454  bar->AddHeader (reqHdr);
455  Bar request (bar, m_currentHdr.GetAddr1 (), tid, reqHdr.MustSendHtImmediateAck ());
456  m_currentBar = request;
457  WifiMacHeader hdr;
459  hdr.SetAddr1 (request.recipient);
460  hdr.SetAddr2 (m_low->GetAddress ());
461  hdr.SetAddr3 (m_low->GetBssid ());
462  hdr.SetDsNotTo ();
463  hdr.SetDsNotFrom ();
464  hdr.SetNoRetry ();
465  hdr.SetNoMoreFragments ();
466  m_currentPacket = request.bar;
467  m_currentHdr = hdr;
468  resetCurrentPacket = false;
469  }
470  }
471  //to reset the dcf.
472  if (resetCurrentPacket == true)
473  {
474  m_currentPacket = 0;
475  }
476  ResetCw ();
477  m_cwTrace = GetCw ();
478  }
479  else
480  {
481  UpdateFailedCw ();
482  m_cwTrace = GetCw ();
483  }
487 }
488 
489 void
491 {
492  NS_LOG_FUNCTION (this);
495  || m_currentHdr.IsQosAmsdu ())
496  {
497  NS_LOG_DEBUG ("got ack. tx done.");
498  if (!m_txOkCallback.IsNull ())
499  {
501  }
502 
503  if (m_currentHdr.IsAction ())
504  {
505  WifiActionHeader actionHdr;
507  p->RemoveHeader (actionHdr);
508  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK
510  {
511  MgtDelBaHeader delBa;
512  p->PeekHeader (delBa);
513  if (delBa.IsByOriginator ())
514  {
515  m_baManager->DestroyAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
516  }
517  else
518  {
520  }
521  }
522  }
523  m_currentPacket = 0;
524  ResetCw ();
525  if (!HasTxop ())
526  {
528  {
530  }
531  m_cwTrace = GetCw ();
535  }
536  }
537  else
538  {
539  NS_LOG_DEBUG ("got ack. tx not done, size=" << m_currentPacket->GetSize ());
540  if (!HasTxop ())
541  {
543  {
545  m_cwTrace = GetCw ();
550  }
551  }
552  }
553 }
554 
555 void
557 {
558  NS_LOG_FUNCTION (this);
559  NS_LOG_DEBUG ("missed ack");
561  {
562  NS_LOG_DEBUG ("Ack Fail");
565  bool resetCurrentPacket = true;
566  if (!m_txFailedCallback.IsNull ())
567  {
569  }
571  {
572  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
573 
575  {
576  //send Block ACK Request in order to shift WinStart at the receiver
577  NS_LOG_DEBUG ("Transmit Block Ack Request");
578  CtrlBAckRequestHeader reqHdr;
579  reqHdr.SetType (COMPRESSED_BLOCK_ACK);
581  reqHdr.SetTidInfo (tid);
582  reqHdr.SetHtImmediateAck (true);
583  Ptr<Packet> bar = Create<Packet> ();
584  bar->AddHeader (reqHdr);
585  Bar request (bar, m_currentHdr.GetAddr1 (), tid, reqHdr.MustSendHtImmediateAck ());
586  m_currentBar = request;
587  WifiMacHeader hdr;
589  hdr.SetAddr1 (request.recipient);
590  hdr.SetAddr2 (m_low->GetAddress ());
591  hdr.SetAddr3 (m_low->GetBssid ());
592  hdr.SetDsNotTo ();
593  hdr.SetDsNotFrom ();
594  hdr.SetNoRetry ();
595  hdr.SetNoMoreFragments ();
596  m_currentPacket = request.bar;
597  m_currentHdr = hdr;
598  resetCurrentPacket = false;
599  }
600  }
601  //to reset the dcf.
602  if (resetCurrentPacket == true)
603  {
604  m_currentPacket = 0;
605  }
606  ResetCw ();
607  m_cwTrace = GetCw ();
608  }
609  else
610  {
611  NS_LOG_DEBUG ("Retransmit");
613  UpdateFailedCw ();
614  m_cwTrace = GetCw ();
615  }
619 }
620 
621 void
622 QosTxop::MissedBlockAck (uint8_t nMpdus)
623 {
624  NS_LOG_FUNCTION (this << +nMpdus);
625  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
627  {
628  m_stationManager->ReportAmpduTxStatus (m_currentHdr.GetAddr1 (), tid, 0, nMpdus, 0, 0);
629  }
630  if (NeedBarRetransmission ())
631  {
633  {
634  //should i report this to station addressed by ADDR1?
635  NS_LOG_DEBUG ("Retransmit block ack request");
637  }
638  else
639  {
640  //standard says when losing a BlockAck originator may send a BAR page 139
641  NS_LOG_DEBUG ("Transmit Block Ack Request");
642  CtrlBAckRequestHeader reqHdr;
643  reqHdr.SetType (COMPRESSED_BLOCK_ACK);
644  if (m_currentHdr.IsQosData ())
645  {
647  }
648  else if (m_currentHdr.IsBlockAckReq ())
649  {
650  CtrlBAckRequestHeader baReqHdr;
651  m_currentPacket->PeekHeader (baReqHdr);
652  reqHdr.SetStartingSequence (baReqHdr.GetStartingSequence ());
653  }
654  else if (m_currentHdr.IsBlockAck ())
655  {
656  CtrlBAckResponseHeader baRespHdr;
657  m_currentPacket->PeekHeader (baRespHdr);
659  }
660  reqHdr.SetTidInfo (tid);
661  reqHdr.SetHtImmediateAck (true);
662  Ptr<Packet> bar = Create<Packet> ();
663  bar->AddHeader (reqHdr);
664  Bar request (bar, m_currentHdr.GetAddr1 (), tid, reqHdr.MustSendHtImmediateAck ());
665  m_currentBar = request;
666  WifiMacHeader hdr;
668  hdr.SetAddr1 (request.recipient);
669  hdr.SetAddr2 (m_low->GetAddress ());
670  hdr.SetAddr3 (m_low->GetBssid ());
671  hdr.SetDsNotTo ();
672  hdr.SetDsNotFrom ();
673  hdr.SetNoRetry ();
674  hdr.SetNoMoreFragments ();
675 
676  m_currentPacket = request.bar;
677  m_currentHdr = hdr;
678  }
679  UpdateFailedCw ();
680  m_cwTrace = GetCw ();
681  }
682  else
683  {
684  NS_LOG_DEBUG ("Block Ack Request Fail");
685  //to reset the dcf.
686  m_currentPacket = 0;
687  ResetCw ();
688  m_cwTrace = GetCw ();
689  }
693 }
694 
697 {
698  return m_msduAggregator;
699 }
700 
703 {
704  return m_mpduAggregator;
705 }
706 
707 void
709 {
710  NS_LOG_FUNCTION (this);
711  if ((m_currentPacket != 0
712  || !m_queue->IsEmpty () || m_baManager->HasPackets ())
713  && !IsAccessRequested ())
714  {
715  Ptr<const Packet> packet;
716  WifiMacHeader hdr;
717  if (m_currentPacket != 0)
718  {
719  packet = m_currentPacket;
720  hdr = m_currentHdr;
721  }
722  else if (m_baManager->HasPackets ())
723  {
724  packet = m_baManager->GetNextPacket (hdr, false);
725  }
726  else
727  {
728  Ptr<const WifiMacQueueItem> item = m_queue->PeekFirstAvailable (m_qosBlockedDestinations);
729  if (item)
730  {
731  packet = item->GetPacket ();
732  hdr = item->GetHeader ();
733  m_currentPacketTimestamp = item->GetTimeStamp ();
734  }
735  }
736  if (packet != 0)
737  {
738  m_isAccessRequestedForRts = m_stationManager->NeedRts (hdr.GetAddr1 (), &hdr, packet, m_low->GetDataTxVector (packet, &hdr));
739  }
740  else
741  {
743  }
745  }
746 }
747 
748 void
750 {
751  //NS_LOG_FUNCTION (this);
752  if (m_currentPacket == 0
753  && (!m_queue->IsEmpty () || m_baManager->HasPackets ())
754  && !IsAccessRequested ())
755  {
756  Ptr<const Packet> packet;
757  WifiMacHeader hdr;
758  if (m_baManager->HasPackets ())
759  {
760  packet = m_baManager->GetNextPacket (hdr, false);
761  }
762  else
763  {
764  Ptr<const WifiMacQueueItem> item = m_queue->PeekFirstAvailable (m_qosBlockedDestinations);
765  if (item)
766  {
767  packet = item->GetPacket ();
768  hdr = item->GetHeader ();
769  m_currentPacketTimestamp = item->GetTimeStamp ();
770  }
771  }
772  if (packet != 0)
773  {
774  m_isAccessRequestedForRts = m_stationManager->NeedRts (hdr.GetAddr1 (), &hdr, packet, m_low->GetDataTxVector (packet, &hdr));
775  }
776  else
777  {
779  }
781  }
782 }
783 
784 bool
786 {
787  uint8_t tid = 0;
788  uint16_t seqNumber = 0;
789  if (m_currentHdr.IsQosData ())
790  {
791  tid = m_currentHdr.GetQosTid ();
792  seqNumber = m_currentHdr.GetSequenceNumber ();
793  }
794  else if (m_currentHdr.IsBlockAckReq ())
795  {
796  CtrlBAckRequestHeader baReqHdr;
797  m_currentPacket->PeekHeader (baReqHdr);
798  tid = baReqHdr.GetTidInfo ();
799  seqNumber = baReqHdr.GetStartingSequence ();
800  }
801  else if (m_currentHdr.IsBlockAck ())
802  {
803  CtrlBAckResponseHeader baRespHdr;
804  m_currentPacket->PeekHeader (baRespHdr);
805  tid = baRespHdr.GetTidInfo ();
806  seqNumber = m_currentHdr.GetSequenceNumber ();
807  }
808  return m_baManager->NeedBarRetransmission (tid, seqNumber, m_currentHdr.GetAddr1 ());
809 }
810 
811 void
813 {
814  NS_LOG_FUNCTION (this);
815  Time txopLimit = GetTxopLimit ();
816  NS_ASSERT (txopLimit.IsZero () || Simulator::Now () - m_startTxop <= txopLimit);
818  Ptr<const Packet> peekedPacket = m_baManager->GetNextPacket (hdr, true);
819  if (peekedPacket == 0)
820  {
821  Ptr<const WifiMacQueueItem> peekedItem = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
823  if (peekedItem)
824  {
825  peekedPacket = peekedItem->GetPacket ();
826  hdr = peekedItem->GetHeader ();
827  }
828  }
829  if ((m_currentHdr.IsQosBlockAck () && peekedPacket == 0) || m_baManager->HasBar (m_currentBar))
830  {
832  return;
833  }
834  else if (peekedPacket == 0)
835  {
836  if (txopLimit.IsStrictlyPositive ())
837  {
838  NS_ASSERT (Simulator::Now () - m_startTxop <= txopLimit);
840  }
841  return;
842  }
845  {
847  }
848  else
849  {
851  }
852  if (txopLimit >= GetLow ()->CalculateOverallTxTime (peekedPacket, &hdr, m_currentParams))
853  {
854  NS_LOG_DEBUG ("start next packet");
855  Ptr<WifiMacQueueItem> item = m_queue->DequeueByTidAndAddress (m_currentHdr.GetQosTid (),
857  NS_ASSERT (item != 0);
858  m_currentPacket = item->GetPacket ();
859  m_currentHdr = item->GetHeader ();
860  NS_ASSERT (m_currentPacket != 0);
861  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
862  m_currentHdr.SetSequenceNumber (sequence);
867  m_fragmentNumber = 0;
868  VerifyBlockAck ();
871  {
872  CompleteTx ();
873  }
874  }
875  else if (txopLimit.IsStrictlyPositive ())
876  {
878  }
879 }
880 
881 Time
883 {
884  Time remainingTxop = GetTxopLimit ();
885  remainingTxop -= (Simulator::Now () - m_startTxop);
886  if (remainingTxop.IsStrictlyNegative ())
887  {
888  remainingTxop = Seconds (0);
889  }
890  NS_LOG_FUNCTION (this << remainingTxop);
891  return remainingTxop;
892 }
893 
894 bool
895 QosTxop::HasTxop (void) const
896 {
897  NS_LOG_FUNCTION (this);
898  WifiMacHeader hdr;
899  if (!m_currentHdr.IsQosData () || GetTxopLimit ().IsZero ())
900  {
901  return false;
902  }
903 
904  Ptr<const WifiMacQueueItem> peekedItem = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
906  if (peekedItem == 0)
907  {
908  return false;
909  }
910 
911  Ptr<const Packet> peekedPacket = peekedItem->GetPacket ();
912  hdr = peekedItem->GetHeader ();
915  {
916  params.DisableAck ();
917  }
918  else
919  {
920  params.EnableAck ();
921  }
922 
923  Time duration = GetLow ()->CalculateOverallTxTime (peekedPacket, &hdr, params);
924  if (m_currentPacket != 0)
925  {
926  //take into account current transmission in duration
927  duration += GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, params);
928  }
929  return (GetTxopRemaining () >= duration);
930 }
931 
932 void
934 {
935  NS_LOG_FUNCTION (this);
936  NS_LOG_DEBUG ("a transmission that did not require an ACK just finished");
938  {
940  }
941  m_currentPacket = 0;
942  ResetCw ();
943  m_cwTrace = GetCw ();
947 }
948 
949 bool
951 {
952  NS_LOG_FUNCTION (this);
957  && m_currentHdr.IsQosData ()
960  {
961  //MSDU is not fragmented when it is transmitted using an HT-immediate or
962  //HT-delayed Block Ack agreement or when it is carried in an A-MPDU.
963  return false;
964  }
965  bool needTxopFragmentation = false;
967  {
969  }
970  return (needTxopFragmentation || m_stationManager->NeedFragmentation (m_currentHdr.GetAddr1 (), &m_currentHdr, m_currentPacket));
971 }
972 
973 bool
975 {
976  if (GetTxopLimit ().IsZero ())
977  {
978  return false;
979  }
982  {
983  return true;
984  }
985  return false;
986 }
987 
988 uint32_t
990 {
991  Time txopDuration = GetTxopLimit ();
992  if (txopDuration.IsZero ())
993  {
994  return 0;
995  }
996  uint32_t maxSize = m_currentPacket->GetSize ();
997  uint32_t minSize = 0;
998  uint32_t size = 0;
999  bool found = false;
1000  while (!found)
1001  {
1002  size = (minSize + ((maxSize - minSize) / 2));
1003  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) > txopDuration)
1004  {
1005  maxSize = size;
1006  }
1007  else
1008  {
1009  minSize = size;
1010  }
1011  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) <= txopDuration
1012  && GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size + 1) > txopDuration)
1013  {
1014  found = true;
1015  }
1016  }
1017  NS_ASSERT (size != 0);
1018  return size;
1019 }
1020 
1021 uint32_t
1023 {
1024  uint32_t fragmentSize = GetTxopFragmentSize ();
1025  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1026  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1027  {
1028  nFragments++;
1029  }
1030  NS_LOG_DEBUG ("GetNTxopFragment returning " << nFragments);
1031  return nFragments;
1032 }
1033 
1034 uint32_t
1035 QosTxop::GetTxopFragmentOffset (uint32_t fragmentNumber) const
1036 {
1037  if (fragmentNumber == 0)
1038  {
1039  return 0;
1040  }
1041  uint32_t offset = 0;
1042  uint32_t fragmentSize = GetTxopFragmentSize ();
1043  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1044  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1045  {
1046  nFragments++;
1047  }
1048  if (fragmentNumber < nFragments)
1049  {
1050  offset = (fragmentNumber * fragmentSize);
1051  }
1052  else
1053  {
1054  NS_ASSERT (false);
1055  }
1056  NS_LOG_DEBUG ("GetTxopFragmentOffset returning " << offset);
1057  return offset;
1058 }
1059 
1060 uint32_t
1061 QosTxop::GetNextTxopFragmentSize (uint32_t fragmentNumber) const
1062 {
1063  NS_LOG_FUNCTION (this << fragmentNumber);
1064  uint32_t fragmentSize = GetTxopFragmentSize ();
1065  uint32_t nFragments = GetNTxopFragment ();
1066  if (fragmentNumber >= nFragments)
1067  {
1068  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning 0");
1069  return 0;
1070  }
1071  if (fragmentNumber == nFragments - 1)
1072  {
1073  fragmentSize = (m_currentPacket->GetSize () - ((nFragments - 1) * fragmentSize));
1074  }
1075  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning " << fragmentSize);
1076  return fragmentSize;
1077 }
1078 
1079 uint32_t
1081 {
1082  uint32_t size;
1083  if (IsTxopFragmentation ())
1084  {
1086  }
1087  else
1088  {
1090  }
1091  return size;
1092 }
1093 
1094 uint32_t
1096 {
1097  uint32_t size;
1098  if (IsTxopFragmentation ())
1099  {
1101  }
1102  else
1103  {
1105  }
1106  return size;
1107 }
1108 
1109 uint32_t
1111 {
1112  uint32_t offset;
1113  if (IsTxopFragmentation ())
1114  {
1116  }
1117  else
1118  {
1121  }
1122  return offset;
1123 }
1124 
1125 bool
1127 {
1128  bool isLastFragment;
1129  if (IsTxopFragmentation ())
1130  {
1131  isLastFragment = (m_fragmentNumber == GetNTxopFragment () - 1);
1132  }
1133  else
1134  {
1137  }
1138  return isLastFragment;
1139 }
1140 
1143 {
1144  NS_LOG_FUNCTION (this << hdr);
1145  *hdr = m_currentHdr;
1147  uint32_t startOffset = GetFragmentOffset ();
1148  Ptr<Packet> fragment;
1149  if (IsLastFragment ())
1150  {
1151  hdr->SetNoMoreFragments ();
1152  }
1153  else
1154  {
1155  hdr->SetMoreFragments ();
1156  }
1157  fragment = m_currentPacket->CreateFragment (startOffset,
1158  GetFragmentSize ());
1159  return fragment;
1160 }
1161 
1162 void
1164 {
1165  NS_LOG_FUNCTION (this << +ac);
1166  m_ac = ac;
1167 }
1168 
1171 {
1172  NS_LOG_FUNCTION (this << &hdr);
1173  Mac48Address retval;
1174  if (GetTypeOfStation () == STA || GetTypeOfStation () == ADHOC_STA)
1175  {
1176  retval = hdr.GetAddr2 ();
1177  }
1178  else
1179  {
1180  retval = hdr.GetAddr3 ();
1181  }
1182  return retval;
1183 }
1184 
1187 {
1188  NS_LOG_FUNCTION (this << &hdr);
1189  Mac48Address retval;
1190  if (GetTypeOfStation () == AP || GetTypeOfStation () == ADHOC_STA)
1191  {
1192  retval = hdr.GetAddr1 ();
1193  }
1194  else
1195  {
1196  retval = hdr.GetAddr3 ();
1197  }
1198  return retval;
1199 }
1200 
1201 void
1203 {
1204  NS_LOG_FUNCTION (this << aggr);
1205  m_msduAggregator = aggr;
1206 }
1207 
1208 void
1210 {
1211  NS_LOG_FUNCTION (this << aggr);
1212  m_mpduAggregator = aggr;
1213 }
1214 
1215 void
1217 {
1218  NS_LOG_FUNCTION (this << packet << &hdr);
1219  WifiMacTrailer fcs;
1220  m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr, packet);
1221  m_queue->PushFront (Create<WifiMacQueueItem> (packet, hdr));
1223 }
1224 
1225 void
1227 {
1228  NS_LOG_FUNCTION (this << respHdr << recipient);
1229  NS_LOG_DEBUG ("received ADDBA response from " << recipient);
1230  uint8_t tid = respHdr->GetTid ();
1231  if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::PENDING))
1232  {
1233  if (respHdr->GetStatusCode ().IsSuccess ())
1234  {
1235  NS_LOG_DEBUG ("block ack agreement established with " << recipient);
1236  m_baManager->UpdateAgreement (respHdr, recipient);
1237  }
1238  else
1239  {
1240  NS_LOG_DEBUG ("discard ADDBA response" << recipient);
1241  m_baManager->NotifyAgreementUnsuccessful (recipient, tid);
1242  }
1243  }
1245 }
1246 
1247 void
1249 {
1250  NS_LOG_FUNCTION (this << delBaHdr << recipient);
1251  NS_LOG_DEBUG ("received DELBA frame from=" << recipient);
1252  m_baManager->DestroyAgreement (recipient, delBaHdr->GetTid ());
1253 }
1254 
1255 void
1256 QosTxop::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, WifiMode txMode, double dataSnr)
1257 {
1258  NS_LOG_FUNCTION (this << blockAck << recipient << rxSnr << txMode.GetUniqueName () << dataSnr);
1259  NS_LOG_DEBUG ("got block ack from=" << recipient);
1260  m_baManager->NotifyGotBlockAck (blockAck, recipient, rxSnr, txMode, dataSnr);
1261  if (!m_txOkCallback.IsNull ())
1262  {
1264  }
1265  m_currentPacket = 0;
1266  ResetCw ();
1267  if (!HasTxop ())
1268  {
1270  {
1272  }
1273  m_cwTrace = GetCw ();
1274  m_backoffTrace = m_rng->GetInteger (0, GetCw ());
1277  }
1278 }
1279 
1280 void
1282 {
1283  NS_LOG_FUNCTION (this);
1284  uint8_t tid = m_currentHdr.GetQosTid ();
1285  Mac48Address recipient = m_currentHdr.GetAddr1 ();
1286  uint16_t sequence = m_currentHdr.GetSequenceNumber ();
1287  if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::INACTIVE))
1288  {
1289  m_baManager->SwitchToBlockAckIfNeeded (recipient, tid, sequence);
1290  }
1291  if ((m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED))
1292  && (GetMpduAggregator () == 0 || GetMpduAggregator ()->GetMaxAmpduSize () == 0))
1293  {
1295  }
1296 }
1297 
1299 {
1300  NS_LOG_FUNCTION (this << dest);
1301  auto it = m_aMpduEnabled.find (dest);
1302  if (it != m_aMpduEnabled.end ())
1303  {
1304  return it->second;
1305  }
1306  return false;
1307 }
1308 
1309 void QosTxop::SetAmpduExist (Mac48Address dest, bool enableAmpdu)
1310 {
1311  NS_LOG_FUNCTION (this << dest << enableAmpdu);
1312  m_aMpduEnabled[dest] = enableAmpdu;
1313 }
1314 
1315 void
1317 {
1318  NS_LOG_FUNCTION (this);
1320  {
1321  if (!m_currentHdr.IsRetry ())
1322  {
1324  }
1325  m_baManager->NotifyMpduTransmission (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid (),
1328  }
1329 }
1330 
1331 void
1333 {
1334  NS_ASSERT (hdr.IsQosData ());
1335  m_baManager->StorePacket (packet, hdr, tstamp);
1336  m_baManager->NotifyMpduTransmission (hdr.GetAddr1 (), hdr.GetQosTid (),
1339 }
1340 
1341 bool
1343 {
1344  NS_LOG_FUNCTION (this);
1345  uint8_t tid = m_currentHdr.GetQosTid ();
1346  Mac48Address recipient = m_currentHdr.GetAddr1 ();
1347  uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, recipient);
1348  if ((GetBlockAckThreshold () > 0 && packets >= GetBlockAckThreshold ())
1349  || (m_mpduAggregator != 0 && m_mpduAggregator->GetMaxAmpduSize () > 0 && packets > 1)
1352  {
1353  /* Block ack setup */
1354  uint16_t startingSequence = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
1355  SendAddBaRequest (recipient, tid, startingSequence, m_blockAckInactivityTimeout, true);
1356  return true;
1357  }
1358  return false;
1359 }
1360 
1361 void
1363 {
1364  NS_LOG_FUNCTION (this << &bar);
1365  WifiMacHeader hdr;
1367  hdr.SetAddr1 (bar.recipient);
1368  hdr.SetAddr2 (m_low->GetAddress ());
1369  hdr.SetAddr3 (m_low->GetBssid ());
1370  hdr.SetDsNotTo ();
1371  hdr.SetDsNotFrom ();
1372  hdr.SetNoRetry ();
1373  hdr.SetNoMoreFragments ();
1374 
1375  m_currentPacket = bar.bar;
1376  m_currentHdr = hdr;
1377 
1380  if (bar.immediate)
1381  {
1383  {
1385  }
1387  {
1389  }
1390  else if (m_blockAckType == MULTI_TID_BLOCK_ACK)
1391  {
1392  NS_FATAL_ERROR ("Multi-tid block ack is not supported");
1393  }
1394  }
1395  else
1396  {
1397  //Delayed block ack
1399  }
1401 }
1402 
1403 void
1405 {
1406  NS_LOG_FUNCTION (this);
1407  m_baManager->SetTxMiddle (m_txMiddle);
1408  m_low->RegisterEdcaForAc (m_ac, this);
1409  m_baManager->SetBlockAckInactivityCallback (MakeCallback (&QosTxop::SendDelbaFrame, this));
1410 }
1411 
1412 void
1414 {
1415  NS_LOG_FUNCTION (this << +threshold);
1416  m_blockAckThreshold = threshold;
1417  m_baManager->SetBlockAckThreshold (threshold);
1418 }
1419 
1420 void
1422 {
1423  NS_LOG_FUNCTION (this << timeout);
1425 }
1426 
1427 uint8_t
1429 {
1430  NS_LOG_FUNCTION (this);
1431  return m_blockAckThreshold;
1432 }
1433 
1434 void
1435 QosTxop::SendAddBaRequest (Mac48Address dest, uint8_t tid, uint16_t startSeq,
1436  uint16_t timeout, bool immediateBAck)
1437 {
1438  NS_LOG_FUNCTION (this << dest << +tid << startSeq << timeout << immediateBAck);
1439  NS_LOG_DEBUG ("sent ADDBA request to " << dest);
1440  WifiMacHeader hdr;
1442  hdr.SetAddr1 (dest);
1443  hdr.SetAddr2 (m_low->GetAddress ());
1444  hdr.SetAddr3 (m_low->GetAddress ());
1445  hdr.SetDsNotTo ();
1446  hdr.SetDsNotFrom ();
1447 
1448  WifiActionHeader actionHdr;
1451  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1452 
1453  Ptr<Packet> packet = Create<Packet> ();
1454  /*Setting ADDBARequest header*/
1455  MgtAddBaRequestHeader reqHdr;
1456  reqHdr.SetAmsduSupport (true);
1457  if (immediateBAck)
1458  {
1459  reqHdr.SetImmediateBlockAck ();
1460  }
1461  else
1462  {
1463  reqHdr.SetDelayedBlockAck ();
1464  }
1465  reqHdr.SetTid (tid);
1466  /* For now we don't use buffer size field in the ADDBA request frame. The recipient
1467  * will choose how many packets it can receive under block ack.
1468  */
1469  reqHdr.SetBufferSize (0);
1470  reqHdr.SetTimeout (timeout);
1471  reqHdr.SetStartingSequence (startSeq);
1472 
1473  m_baManager->CreateAgreement (&reqHdr, dest);
1474 
1475  packet->AddHeader (reqHdr);
1476  packet->AddHeader (actionHdr);
1477 
1478  m_currentPacket = packet;
1479  m_currentHdr = hdr;
1480 
1481  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
1482  m_currentHdr.SetSequenceNumber (sequence);
1487 
1491 
1493 }
1494 
1495 void
1496 QosTxop::SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator)
1497 {
1498  NS_LOG_FUNCTION (this << addr << +tid << byOriginator);
1499  WifiMacHeader hdr;
1501  hdr.SetAddr1 (addr);
1502  hdr.SetAddr2 (m_low->GetAddress ());
1503  hdr.SetAddr3 (m_low->GetAddress ());
1504  hdr.SetDsNotTo ();
1505  hdr.SetDsNotFrom ();
1506 
1507  MgtDelBaHeader delbaHdr;
1508  delbaHdr.SetTid (tid);
1509  if (byOriginator)
1510  {
1511  delbaHdr.SetByOriginator ();
1512  m_baManager->DestroyAgreement (addr, tid);
1513  }
1514  else
1515  {
1516  delbaHdr.SetByRecipient ();
1517  m_low->DestroyBlockAckAgreement (addr, tid);
1518  }
1519 
1520  WifiActionHeader actionHdr;
1523  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1524 
1525  Ptr<Packet> packet = Create<Packet> ();
1526  packet->AddHeader (delbaHdr);
1527  packet->AddHeader (actionHdr);
1528 
1529  PushFront (packet, hdr);
1530 }
1531 
1532 void
1534 {
1535  NS_LOG_FUNCTION (this);
1536  ResetCw ();
1537  m_cwTrace = GetCw ();
1538  m_backoffTrace = m_rng->GetInteger (0, GetCw ());
1540 }
1541 
1542 void
1544 {
1545  NS_LOG_FUNCTION (this << hdr);
1546  if (!m_txOkCallback.IsNull ())
1547  {
1549  }
1550 }
1551 
1552 void
1554 {
1555  NS_LOG_FUNCTION (this << hdr);
1556  if (!m_txFailedCallback.IsNull ())
1557  {
1559  }
1560 }
1561 
1562 bool
1564 {
1565  return true;
1566 }
1567 
1568 } //namespace ns3
1569 
bool HasVhtSupported(void) const
Return whether the device has VHT capability support enabled.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
bool GetBaAgreementExists(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:109
AcIndex m_ac
the access category
Definition: qos-txop.h:540
TxFailed m_txFailedCallback
the transmit failed callback
Definition: txop.h:498
bool IsRetry(void) const
Return if the Retry bit is set.
void SetRetry(void)
Set the Retry bit in the Frame Control field.
bool IsSuccess(void) const
Return whether the status code is success.
Definition: status-code.cc:42
void MissedAck(void)
Event handler when an ACK is missed.
Definition: qos-txop.cc:556
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:882
#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:1298
Ptr< MacTxMiddle > m_txMiddle
the MacTxMiddle
Definition: txop.h:501
void VerifyBlockAck(void)
Verifies if dequeued packet has to be transmitted with ack policy Block Ack.
Definition: qos-txop.cc:1281
Time CalculateOverallTxTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &params, uint32_t fragmentSize=0) const
Definition: mac-low.cc:1181
void RestartAccessIfNeeded(void)
Restart access request if needed.
Definition: qos-txop.cc:708
BlockAckType m_blockAckType
the Block ACK type
Definition: qos-txop.h:547
Ptr< MpduAggregator > GetMpduAggregator(void) const
Returns the aggregator used to construct A-MPDU subframes.
Definition: qos-txop.cc:702
#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:831
void ReportFinalDataFailed(Mac48Address address, const WifiMacHeader *header, uint32_t packetSize)
Should be invoked after calling ReportDataFailed if NeedRetransmission returns false.
Time m_startTxop
the start TXOP time
Definition: qos-txop.h:551
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
Definition: mgt-headers.h:864
Mac48Address MapDestAddressForAggregation(const WifiMacHeader &hdr)
This functions are used only to correctly set destination address in A-MSDU subframes.
Definition: qos-txop.cc:1186
void EnableBasicBlockAck(void)
Wait BASICBLOCKACKTimeout for a Basic Block Ack Response frame.
bool m_isAccessRequestedForRts
flag whether access is requested to transmit a RTS frame
Definition: qos-txop.h:552
bool SetupBlockAckIfNeeded()
If number of packets in the queue reaches m_blockAckThreshold value, an ADDBA Request frame is sent t...
Definition: qos-txop.cc:1342
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:90
void MissedBlockAck(uint8_t nMpdus)
Event handler when a Block ACK timeout has occurred.
Definition: qos-txop.cc:622
Implement the header for management frames of type add block ack request.
Definition: mgt-headers.h:997
bool NeedBarRetransmission(void)
Check if Block ACK Request should be re-transmitted.
Definition: qos-txop.cc:785
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:496
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.
#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
uint32_t GetTxopFragmentSize() const
Calculate the size of the current TXOP fragment.
Definition: qos-txop.cc:989
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
Ptr< MpduAggregator > m_mpduAggregator
A-MPDU aggregator.
Definition: qos-txop.h:542
void SetBlockAckInactivityTimeout(uint16_t timeout)
Set the Block Ack inactivity timeout.
Definition: qos-txop.cc:1421
Mac48Address GetBssid(void) const
Return the Basic Service Set Identification.
Definition: mac-low.cc:426
virtual WifiTxVector GetDataTxVector(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return a TXVECTOR for the DATA frame given the destination.
Definition: mac-low.cc:1144
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:1496
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
void SetHtImmediateAck(bool immediateAck)
Enable or disable HT immediate ACK.
bool IsStrictlyPositive(void) const
Definition: nstime.h:308
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:1248
void UpdateFragmentationThreshold(void)
Typically called to update the fragmentation threshold at the start of a new transmission.
WifiMacType GetType(void) const
Return the type (enum WifiMacType)
bool IsLastFragment(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, uint32_t fragmentNumber)
Ptr< UniformRandomVariable > m_rng
the random stream
Definition: txop.h:504
CategoryValue GetCategory()
Return the category value.
virtual ~QosTxop()
Definition: qos-txop.cc:92
void PrepareForQueue(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
ns3::Time timeout
void SetAccessCategory(AcIndex ac)
Set the access category of this EDCAF.
Definition: qos-txop.cc:1163
virtual void StartTransmission(Ptr< const Packet > packet, const WifiMacHeader *hdr, MacLowTransmissionParameters parameters, Ptr< Txop > txop)
Definition: mac-low.cc:478
uint16_t GetNextSequenceNumberFor(WifiMacHeader *hdr)
Return the next sequence number for the given header.
Definition: qos-txop.cc:142
static TypeId GetTypeId(void)
Get the type ID.
Definition: qos-txop.cc:49
uint8_t GetBlockAckThreshold(void) const
Return the current threshold for block ACK mechanism.
Definition: qos-txop.cc:1428
Block Ack Request.
void DoDispose(void)
Destructor implementation.
Definition: qos-txop.cc:98
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
control how a packet is transmitted.
void SetAmsduSupport(bool supported)
Enable or disable A-MSDU support.
void SetType(BlockAckType type)
Set the block ACK type.
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:1126
void SetMsduAggregator(const Ptr< MsduAggregator > aggr)
Set the aggregator used to construct A-MSDU subframes.
Definition: qos-txop.cc:1202
bool IsTxopFragmentation() const
Check if the current packet is fragmented because of an exceeded TXOP duration.
Definition: qos-txop.cc:974
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.
Ptr< MsduAggregator > m_msduAggregator
A-MSDU aggregator.
Definition: qos-txop.h:541
uint32_t GetFragmentOffset(void) const
Calculate the offset for the current fragment.
Definition: qos-txop.cc:1110
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:212
void DestroyBlockAckAgreement(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2157
virtual uint32_t GetInteger(void)=0
Get the next random value as an integer drawn from the distribution.
bool immediate
immediate
bool MustSendHtImmediateAck(void) const
Check if the current ACK policy is immediate.
Mac48Address GetAddress(void) const
Return the MAC address of this MacLow.
Definition: mac-low.cc:370
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
bool IsZero(void) const
Definition: nstime.h:288
uint16_t GetNextSequenceNumberFor(const WifiMacHeader *hdr)
Return the next sequence number for the given header.
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:1095
void SetAmpduExist(Mac48Address dest, bool enableAmpdu)
Set indication whether A-MPDU is used to transmit data to a peer station.
Definition: qos-txop.cc:1309
void StartAccessIfNeeded(void)
Request access from DCF manager if needed.
Definition: qos-txop.cc:749
void SendBlockAckRequest(const Bar &bar)
After that all packets, for which a block ack agreement was established, have been transmitted...
Definition: qos-txop.cc:1362
Ptr< BlockAckManager > m_baManager
the Block ACK manager
Definition: qos-txop.h:545
void CompleteAmpduTransfer(Mac48Address recipient, uint8_t tid)
Definition: qos-txop.cc:115
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.
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:181
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
void RegisterEdcaForAc(AcIndex ac, Ptr< QosTxop > edca)
Definition: mac-low.cc:2436
TracedValue< uint32_t > m_backoffTrace
backoff trace value
Definition: qos-txop.h:555
uint16_t GetMaxAmpduSize(void) const
Returns the maximum A-MPDU size in bytes.
void GotAddBaResponse(const MgtAddBaResponseHeader *respHdr, Mac48Address recipient)
Event handler when an ADDBA response is received.
Definition: qos-txop.cc:1226
void SetTypeOfStation(TypeOfStation type)
Set type of station with the given type.
Definition: qos-txop.cc:129
virtual bool IsAccessRequested(void) const
Definition: txop.cc:435
bool GetQosSupported(Mac48Address address) const
Return whether the given station is QoS capable.
std::string GetUniqueName(void) const
Definition: wifi-mode.cc:463
void MissedCts(void)
Event handler when a CTS timeout has occurred.
Definition: qos-txop.cc:427
uint32_t GetFragmentSize(void) const
Calculate the size of the current fragment.
Definition: qos-txop.cc:1080
void PushFront(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Definition: qos-txop.cc:1216
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
uint32_t GetNTxopFragment() const
Calculate the number of TXOP fragments needed for the transmission of the current packet...
Definition: qos-txop.cc:1022
Mac48Address recipient
recipient
void SetByOriginator(void)
Set the initiator bit in the DELBA.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
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:353
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:339
bool IsQosTxop() const
Check for QoS TXOP.
Definition: qos-txop.cc:1563
void EnableCompressedBlockAck(void)
Wait COMPRESSEDBLOCKACKTimeout for a Compressed Block Ack Response frame.
void SetMpduAggregator(const Ptr< MpduAggregator > aggr)
Set the aggregator used to construct A-MPDU subframes.
Definition: qos-txop.cc:1209
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool HasHeSupported(void) const
Return whether the device has HE capability support enabled.
uint32_t GetCw(void) const
Definition: txop.cc:199
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
bool IsData(void) const
Return true if the Type is DATA.
address
Definition: first.py:37
StatusCode GetStatusCode(void) const
Return the status code.
void EnableAck(void)
Wait ACKTimeout for an ACK.
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:1553
Bar m_currentBar
the current BAR
Definition: qos-txop.h:550
uint32_t GetFragmentSize(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, uint32_t fragmentNumber)
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:500
virtual void DoDispose(void)
Destructor implementation.
Definition: txop.cc:97
an EUI-48 address
Definition: mac48-address.h:43
bool NeedDataRetransmission(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Check if DATA should be re-transmitted if ACK was missed.
Definition: txop.cc:360
void BaTxOk(const WifiMacHeader &hdr)
The packet we sent was successfully received by the receiver.
Definition: qos-txop.cc:1543
Ptr< const Packet > m_currentPacket
the current packet
Definition: txop.h:521
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
uint8_t GetTid(Ptr< const Packet > packet, const WifiMacHeader hdr)
Extraction operator for TypeId.
Definition: qos-utils.cc:98
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:933
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:249
uint16_t PeekNextSequenceNumberFor(const WifiMacHeader *hdr)
Return the next sequence number for the Traffic ID and destination, but do not pick it (i...
bool HasHtSupported(void) const
Return whether the device has HT capability support enabled.
void SetBlockAckThreshold(uint8_t threshold)
Set threshold for block ACK mechanism.
Definition: qos-txop.cc:1413
TracedValue< uint32_t > m_cwTrace
CW trace value.
Definition: qos-txop.h:556
Ptr< MacLow > m_low
the MacLow
Definition: txop.h:502
uint8_t m_blockAckThreshold
the Block ACK threshold
Definition: qos-txop.h:546
void FlushAggregateQueue(uint8_t tid)
This function is called to flush the aggregate queue, which is used for A-MPDU.
Definition: mac-low.cc:2875
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > remoteManager)
Set WifiRemoteStationsManager this QosTxop is associated to.
Definition: qos-txop.cc:121
uint32_t GetTxopFragmentOffset(uint32_t fragmentNumber) const
Calculate the offset for the fragment.
Definition: qos-txop.cc:1035
void NotifyCollision(void)
Notify the EDCAF that collision has occurred.
Definition: qos-txop.cc:418
void RemoveRetransmitPacket(uint8_t tid, Mac48Address recipient, uint16_t seqnumber)
Remove a packet after you peek in the retransmit queue and get it.
Definition: qos-txop.cc:160
Ptr< const Packet > PeekNextRetransmitPacket(WifiMacHeader &header, uint8_t tid, Time *timestamp)
Peek in retransmit queue and get the next packet without removing it from the queue.
Definition: qos-txop.cc:154
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
bool IsQosBlockAck(void) const
Return if the QoS ACK policy is Block ACK.
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:523
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:1256
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:490
void StartNextPacket(void)
Start transmission for the next packet if allowed by the TxopLimit.
Definition: qos-txop.cc:812
bool m_accessRequested
flag whether channel access is already requested
Definition: txop.h:509
BlockAckActionValue blockAck
block ack
Definition: mgt-headers.h:940
void Unblock(Mac48Address dest, uint8_t tid)
Un-block the given destination address and TID (e.g.
void CompleteTx(void)
For now is typically invoked to complete transmission of a packets sent with ack policy Block Ack: th...
Definition: qos-txop.cc:1316
Implement the header for management frames of type add block ack response.
Definition: mgt-headers.h:1129
bool IsStrictlyNegative(void) const
Definition: nstime.h:303
Implement the header for management frames of type del block ack.
Definition: mgt-headers.h:1250
Mac48Address MapSrcAddressForAggregation(const WifiMacHeader &hdr)
This functions are used only to correctly set source address in A-MSDU subframes. ...
Definition: qos-txop.cc:1170
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:270
TypeOfStation GetTypeOfStation(void) const
Return type of station.
Definition: qos-txop.cc:136
typedef for union of different ActionValues
Definition: mgt-headers.h:935
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1014
Ptr< const Packet > bar
block ack request
Ptr< QosBlockedDestinations > m_qosBlockedDestinations
QOS blocked destinations.
Definition: qos-txop.h:544
void NotifyAccessGranted(void)
Notify the EDCAF that access has been granted.
Definition: qos-txop.cc:166
uint16_t GetNextSeqNumberByTidAndAddress(uint8_t tid, Mac48Address addr) const
Return the next sequence number for the Traffic ID and destination.
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.
void CompleteMpduTx(Ptr< const Packet > packet, WifiMacHeader hdr, Time tstamp)
Stores an MPDU (part of an A-MPDU) in blockackagreement (i.e.
Definition: qos-txop.cc:1332
TxOk m_txOkCallback
the transmit OK callback
Definition: txop.h:497
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:130
void CompleteConfig(void)
Complete block ACK configuration.
Definition: qos-txop.cc:1404
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:553
bool IsAction() const
Return true if the header is an Action header.
uint8_t m_fragmentNumber
the fragment number
Definition: txop.h:524
TracedCallback< Time, Time > m_txopTrace
TXOP trace callback.
Definition: qos-txop.h:557
void DoInitialize(void)
Initialize() implementation.
Definition: qos-txop.cc:1533
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).
bool NeedFragmentation(void) const
Check if the current packet should be fragmented.
Definition: qos-txop.cc:950
TypeOfStation
Enumeration for type of station.
Definition: qos-txop.h:45
WifiMacHeader m_currentHdr
the current header
Definition: txop.h:522
Time m_currentPacketTimestamp
the current packet timestamp
Definition: qos-txop.h:548
Ptr< Packet > GetFragmentPacket(WifiMacHeader *hdr)
Get the next fragment from the packet with appropriate Wifi header for the fragment.
Definition: qos-txop.cc:1142
ActionValue GetAction()
Return the action value.
uint16_t m_blockAckInactivityTimeout
the Block ACK inactivity timeout
Definition: qos-txop.h:549
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:503
bool HasTxop(void) const
Check if the station has TXOP granted for the next MPDU.
Definition: qos-txop.cc:895
void SetFragmentNumber(uint8_t frag)
Set the fragment number of the header.
bool Aggregate(Ptr< const Packet > packet, Ptr< Packet > aggregatedPacket, Mac48Address src, Mac48Address dest) const
Adds packet to aggregatedPacket.
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:328
void ResetCw(void)
Update the value of the CW variable to take into account a transmission success or a transmission abo...
Definition: txop.cc:205
uint32_t GetNextTxopFragmentSize(uint32_t fragmentNumber) const
Calculate the size of the next TXOP fragment.
Definition: qos-txop.cc:1061
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
TypeOfStation m_typeOfStation
the type of station
Definition: qos-txop.h:543
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.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:915
void SetQosAmsdu(void)
Set that A-MSDU is present.
void StartBackoffNow(uint32_t nSlots)
Definition: txop.cc:241
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:37
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.
std::map< Mac48Address, bool > m_aMpduEnabled
list containing flags whether A-MPDU is enabled for a given destination address
Definition: qos-txop.h:96
Implements the IEEE 802.11 MAC trailer.
Ptr< MsduAggregator > GetMsduAggregator(void) const
Returns the aggregator used to construct A-MSDU subframes.
Definition: qos-txop.cc:696
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:1435
uint16_t GetSequenceControl(void) const
Return the raw Sequence Control field.
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:64
uint16_t PeekNextSequenceNumberFor(WifiMacHeader *hdr)
Return the next sequence number for the Traffic ID and destination, but do not pick it (i...
Definition: qos-txop.cc:148
Time GetTxopLimit(void) const
Return the TXOP limit.
Definition: txop.cc:290
void SetQosAckPolicy(QosAckPolicy policy)
Set the QoS ACK policy in the QoS control field.