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),
76  m_startTxop (Seconds (0)),
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);
85  m_baManager->SetBlockDestinationCallback (MakeCallback (&QosBlockedDestinations::Block, m_qosBlockedDestinations));
86  m_baManager->SetUnblockDestinationCallback (MakeCallback (&QosBlockedDestinations::Unblock, m_qosBlockedDestinations));
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 (),
292  while (peekedItem != 0)
293  {
294  peekedHdr = peekedItem->GetHeader ();
295  aggregated = m_msduAggregator->Aggregate (peekedItem->GetPacket (), currentAggregatedPacket,
296  MapSrcAddressForAggregation (peekedHdr),
297  MapDestAddressForAggregation (peekedHdr));
298  if (aggregated)
299  {
300  isAmsdu = true;
301  m_queue->Remove (peekedItem->GetPacket ());
302  }
303  else
304  {
305  break;
306  }
307  peekedItem = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
309  }
310  if (isAmsdu)
311  {
314  m_currentPacket = currentAggregatedPacket;
315  currentAggregatedPacket = 0;
316  NS_LOG_DEBUG ("tx unicast A-MSDU");
317  }
318  }
322  {
323  CompleteTx ();
324  }
325  }
326  }
327 }
328 
330 {
331  NS_LOG_FUNCTION (this);
332  bool resetDcf = false;
333  // If an internal collision is experienced, the frame involved may still
334  // be sitting in the queue, and m_currentPacket may still be null.
335  Ptr<const Packet> packet;
336  WifiMacHeader header;
337  if (m_currentPacket == 0)
338  {
339  if (m_baManager->HasPackets ())
340  {
341  packet = m_baManager->GetNextPacket (header, false);
342  }
343  else
344  {
345  Ptr<const WifiMacQueueItem> item = m_queue->Peek ();
346  if (item)
347  {
348  packet = item->GetPacket ();
349  header = item->GetHeader ();
350  }
351  }
352  }
353  else
354  {
355  packet = m_currentPacket;
356  header = m_currentHdr;
357  }
358  if (packet != 0)
359  {
361  {
362  if (!NeedRtsRetransmission (packet, header))
363  {
364  resetDcf = true;
365  m_stationManager->ReportFinalRtsFailed (header.GetAddr1 (), &header);
366  }
367  else
368  {
369  m_stationManager->ReportRtsFailed (header.GetAddr1 (), &header);
370  }
371  }
372  else if (header.GetAddr1 () == Mac48Address::GetBroadcast ())
373  {
374  resetDcf = false;
375  }
376  else
377  {
378  if (!NeedDataRetransmission (packet, header))
379  {
380  resetDcf = true;
381  m_stationManager->ReportFinalDataFailed (header.GetAddr1 (), &header);
382  }
383  else
384  {
385  m_stationManager->ReportDataFailed (header.GetAddr1 (), &header);
386  }
387  }
388  if (resetDcf)
389  {
390  NS_LOG_DEBUG ("reset DCF");
391  if (!m_txFailedCallback.IsNull ())
392  {
393  m_txFailedCallback (header);
394  }
395  //to reset the dcf.
396  if (m_currentPacket)
397  {
398  NS_LOG_DEBUG ("Discarding m_currentPacket");
399  m_currentPacket = 0;
400  }
401  else
402  {
403  NS_LOG_DEBUG ("Dequeueing and discarding head of queue");
404  m_queue->Remove ();
405  }
406  ResetCw ();
407  }
408  else
409  {
410  UpdateFailedCw ();
411  }
412  }
416 }
417 
418 void
420 {
421  NS_LOG_FUNCTION (this);
425 }
426 
427 void
429 {
430  NS_LOG_FUNCTION (this);
431  NS_LOG_DEBUG ("missed cts");
433  {
434  NS_LOG_DEBUG ("Cts Fail");
435  bool resetCurrentPacket = true;
437  if (!m_txFailedCallback.IsNull ())
438  {
440  }
442  {
443  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
444  m_low->FlushAggregateQueue (tid);
445 
447  {
448  NS_LOG_DEBUG ("Transmit Block Ack Request");
449  CtrlBAckRequestHeader reqHdr;
450  reqHdr.SetType (COMPRESSED_BLOCK_ACK);
452  reqHdr.SetTidInfo (tid);
453  reqHdr.SetHtImmediateAck (true);
454  Ptr<Packet> bar = Create<Packet> ();
455  bar->AddHeader (reqHdr);
456  Bar request (bar, m_currentHdr.GetAddr1 (), tid, reqHdr.MustSendHtImmediateAck ());
457  m_currentBar = request;
458  WifiMacHeader hdr;
460  hdr.SetAddr1 (request.recipient);
461  hdr.SetAddr2 (m_low->GetAddress ());
462  hdr.SetAddr3 (m_low->GetBssid ());
463  hdr.SetDsNotTo ();
464  hdr.SetDsNotFrom ();
465  hdr.SetNoRetry ();
466  hdr.SetNoMoreFragments ();
467  m_currentPacket = request.bar;
468  m_currentHdr = hdr;
469  resetCurrentPacket = false;
470  }
471  }
472  //to reset the dcf.
473  if (resetCurrentPacket == true)
474  {
475  m_currentPacket = 0;
476  }
477  ResetCw ();
478  m_cwTrace = GetCw ();
479  }
480  else
481  {
482  UpdateFailedCw ();
483  m_cwTrace = GetCw ();
484  }
488 }
489 
490 void
492 {
493  NS_LOG_FUNCTION (this);
496  || m_currentHdr.IsQosAmsdu ())
497  {
498  NS_LOG_DEBUG ("got ack. tx done.");
499  if (!m_txOkCallback.IsNull ())
500  {
502  }
503 
504  if (m_currentHdr.IsAction ())
505  {
506  WifiActionHeader actionHdr;
508  p->RemoveHeader (actionHdr);
509  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK
511  {
512  MgtDelBaHeader delBa;
513  p->PeekHeader (delBa);
514  if (delBa.IsByOriginator ())
515  {
516  m_baManager->DestroyAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
517  }
518  else
519  {
521  }
522  }
523  }
524  m_currentPacket = 0;
525  ResetCw ();
526  if (!HasTxop ())
527  {
529  {
531  }
532  m_cwTrace = GetCw ();
536  }
537  }
538  else
539  {
540  NS_LOG_DEBUG ("got ack. tx not done, size=" << m_currentPacket->GetSize ());
541  if (!HasTxop ())
542  {
544  {
546  m_cwTrace = GetCw ();
551  }
552  }
553  }
554 }
555 
556 void
558 {
559  NS_LOG_FUNCTION (this);
560  NS_LOG_DEBUG ("missed ack");
562  {
563  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 (),
824  if (peekedItem)
825  {
826  peekedPacket = peekedItem->GetPacket ();
827  hdr = peekedItem->GetHeader ();
828  }
829  }
830  if ((m_currentHdr.IsQosBlockAck () && peekedPacket == 0) || m_baManager->HasBar (m_currentBar))
831  {
833  return;
834  }
835  else if (peekedPacket == 0)
836  {
837  if (txopLimit.IsStrictlyPositive ())
838  {
839  NS_ASSERT (Simulator::Now () - m_startTxop <= txopLimit);
841  }
842  return;
843  }
846  {
848  }
849  else
850  {
852  }
853  if (txopLimit >= GetLow ()->CalculateOverallTxTime (peekedPacket, &hdr, m_currentParams))
854  {
855  NS_LOG_DEBUG ("start next packet");
856  Ptr<WifiMacQueueItem> item = m_queue->DequeueByTidAndAddress (m_currentHdr.GetQosTid (),
859  NS_ASSERT (item != 0);
860  m_currentPacket = item->GetPacket ();
861  m_currentHdr = item->GetHeader ();
862  NS_ASSERT (m_currentPacket != 0);
863  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
864  m_currentHdr.SetSequenceNumber (sequence);
869  m_fragmentNumber = 0;
870  VerifyBlockAck ();
873  {
874  CompleteTx ();
875  }
876  }
877  else if (txopLimit.IsStrictlyPositive ())
878  {
880  }
881 }
882 
883 Time
885 {
886  Time remainingTxop = GetTxopLimit ();
887  remainingTxop -= (Simulator::Now () - m_startTxop);
888  if (remainingTxop.IsStrictlyNegative ())
889  {
890  remainingTxop = Seconds (0);
891  }
892  NS_LOG_FUNCTION (this << remainingTxop);
893  return remainingTxop;
894 }
895 
896 bool
897 QosTxop::HasTxop (void) const
898 {
899  NS_LOG_FUNCTION (this);
900  WifiMacHeader hdr;
901  if (!m_currentHdr.IsQosData () || GetTxopLimit ().IsZero ())
902  {
903  return false;
904  }
905 
906  Ptr<const WifiMacQueueItem> peekedItem = m_queue->PeekByTidAndAddress (m_currentHdr.GetQosTid (),
909  if (peekedItem == 0)
910  {
911  return false;
912  }
913 
914  Ptr<const Packet> peekedPacket = peekedItem->GetPacket ();
915  hdr = peekedItem->GetHeader ();
918  {
919  params.DisableAck ();
920  }
921  else
922  {
923  params.EnableAck ();
924  }
925 
926  Time duration = GetLow ()->CalculateOverallTxTime (peekedPacket, &hdr, params);
927  if (m_currentPacket != 0)
928  {
929  //take into account current transmission in duration
930  duration += GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, params);
931  }
932  return (GetTxopRemaining () >= duration);
933 }
934 
935 void
937 {
938  NS_LOG_FUNCTION (this);
939  NS_LOG_DEBUG ("a transmission that did not require an ACK just finished");
941  {
943  }
944  m_currentPacket = 0;
945  ResetCw ();
946  m_cwTrace = GetCw ();
950 }
951 
952 bool
954 {
955  NS_LOG_FUNCTION (this);
960  && m_currentHdr.IsQosData ()
963  {
964  //MSDU is not fragmented when it is transmitted using an HT-immediate or
965  //HT-delayed Block Ack agreement or when it is carried in an A-MPDU.
966  return false;
967  }
968  bool needTxopFragmentation = false;
970  {
972  }
973  return (needTxopFragmentation || m_stationManager->NeedFragmentation (m_currentHdr.GetAddr1 (), &m_currentHdr, m_currentPacket));
974 }
975 
976 bool
978 {
979  if (GetTxopLimit ().IsZero ())
980  {
981  return false;
982  }
985  {
986  return true;
987  }
988  return false;
989 }
990 
991 uint32_t
993 {
994  Time txopDuration = GetTxopLimit ();
995  if (txopDuration.IsZero ())
996  {
997  return 0;
998  }
999  uint32_t maxSize = m_currentPacket->GetSize ();
1000  uint32_t minSize = 0;
1001  uint32_t size = 0;
1002  bool found = false;
1003  while (!found)
1004  {
1005  size = (minSize + ((maxSize - minSize) / 2));
1006  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) > txopDuration)
1007  {
1008  maxSize = size;
1009  }
1010  else
1011  {
1012  minSize = size;
1013  }
1014  if (GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size) <= txopDuration
1015  && GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, m_currentParams, size + 1) > txopDuration)
1016  {
1017  found = true;
1018  }
1019  }
1020  NS_ASSERT (size != 0);
1021  return size;
1022 }
1023 
1024 uint32_t
1026 {
1027  uint32_t fragmentSize = GetTxopFragmentSize ();
1028  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1029  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1030  {
1031  nFragments++;
1032  }
1033  NS_LOG_DEBUG ("GetNTxopFragment returning " << nFragments);
1034  return nFragments;
1035 }
1036 
1037 uint32_t
1038 QosTxop::GetTxopFragmentOffset (uint32_t fragmentNumber) const
1039 {
1040  if (fragmentNumber == 0)
1041  {
1042  return 0;
1043  }
1044  uint32_t offset = 0;
1045  uint32_t fragmentSize = GetTxopFragmentSize ();
1046  uint32_t nFragments = (m_currentPacket->GetSize () / fragmentSize);
1047  if ((m_currentPacket->GetSize () % fragmentSize) > 0)
1048  {
1049  nFragments++;
1050  }
1051  if (fragmentNumber < nFragments)
1052  {
1053  offset = (fragmentNumber * fragmentSize);
1054  }
1055  else
1056  {
1057  NS_ASSERT (false);
1058  }
1059  NS_LOG_DEBUG ("GetTxopFragmentOffset returning " << offset);
1060  return offset;
1061 }
1062 
1063 uint32_t
1064 QosTxop::GetNextTxopFragmentSize (uint32_t fragmentNumber) const
1065 {
1066  NS_LOG_FUNCTION (this << fragmentNumber);
1067  uint32_t fragmentSize = GetTxopFragmentSize ();
1068  uint32_t nFragments = GetNTxopFragment ();
1069  if (fragmentNumber >= nFragments)
1070  {
1071  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning 0");
1072  return 0;
1073  }
1074  if (fragmentNumber == nFragments - 1)
1075  {
1076  fragmentSize = (m_currentPacket->GetSize () - ((nFragments - 1) * fragmentSize));
1077  }
1078  NS_LOG_DEBUG ("GetNextTxopFragmentSize returning " << fragmentSize);
1079  return fragmentSize;
1080 }
1081 
1082 uint32_t
1084 {
1085  uint32_t size;
1086  if (IsTxopFragmentation ())
1087  {
1089  }
1090  else
1091  {
1093  }
1094  return size;
1095 }
1096 
1097 uint32_t
1099 {
1100  uint32_t size;
1101  if (IsTxopFragmentation ())
1102  {
1104  }
1105  else
1106  {
1108  }
1109  return size;
1110 }
1111 
1112 uint32_t
1114 {
1115  uint32_t offset;
1116  if (IsTxopFragmentation ())
1117  {
1119  }
1120  else
1121  {
1124  }
1125  return offset;
1126 }
1127 
1128 bool
1130 {
1131  bool isLastFragment;
1132  if (IsTxopFragmentation ())
1133  {
1134  isLastFragment = (m_fragmentNumber == GetNTxopFragment () - 1);
1135  }
1136  else
1137  {
1140  }
1141  return isLastFragment;
1142 }
1143 
1146 {
1147  NS_LOG_FUNCTION (this << hdr);
1148  *hdr = m_currentHdr;
1150  uint32_t startOffset = GetFragmentOffset ();
1151  Ptr<Packet> fragment;
1152  if (IsLastFragment ())
1153  {
1154  hdr->SetNoMoreFragments ();
1155  }
1156  else
1157  {
1158  hdr->SetMoreFragments ();
1159  }
1160  fragment = m_currentPacket->CreateFragment (startOffset,
1161  GetFragmentSize ());
1162  return fragment;
1163 }
1164 
1165 void
1167 {
1168  NS_LOG_FUNCTION (this << +ac);
1169  m_ac = ac;
1170 }
1171 
1174 {
1175  NS_LOG_FUNCTION (this << &hdr);
1176  Mac48Address retval;
1177  if (GetTypeOfStation () == STA || GetTypeOfStation () == ADHOC_STA)
1178  {
1179  retval = hdr.GetAddr2 ();
1180  }
1181  else
1182  {
1183  retval = hdr.GetAddr3 ();
1184  }
1185  return retval;
1186 }
1187 
1190 {
1191  NS_LOG_FUNCTION (this << &hdr);
1192  Mac48Address retval;
1193  if (GetTypeOfStation () == AP || GetTypeOfStation () == ADHOC_STA)
1194  {
1195  retval = hdr.GetAddr1 ();
1196  }
1197  else
1198  {
1199  retval = hdr.GetAddr3 ();
1200  }
1201  return retval;
1202 }
1203 
1204 void
1206 {
1207  NS_LOG_FUNCTION (this << aggr);
1208  m_msduAggregator = aggr;
1209 }
1210 
1211 void
1213 {
1214  NS_LOG_FUNCTION (this << aggr);
1215  m_mpduAggregator = aggr;
1216 }
1217 
1218 void
1220 {
1221  NS_LOG_FUNCTION (this << packet << &hdr);
1222  WifiMacTrailer fcs;
1223  m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr, packet);
1224  m_queue->PushFront (Create<WifiMacQueueItem> (packet, hdr));
1226 }
1227 
1228 void
1230 {
1231  NS_LOG_FUNCTION (this << respHdr << recipient);
1232  NS_LOG_DEBUG ("received ADDBA response from " << recipient);
1233  uint8_t tid = respHdr->GetTid ();
1234  if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::PENDING))
1235  {
1236  if (respHdr->GetStatusCode ().IsSuccess ())
1237  {
1238  NS_LOG_DEBUG ("block ack agreement established with " << recipient);
1239  m_baManager->UpdateAgreement (respHdr, recipient);
1240  }
1241  else
1242  {
1243  NS_LOG_DEBUG ("discard ADDBA response" << recipient);
1244  m_baManager->NotifyAgreementUnsuccessful (recipient, tid);
1245  }
1246  }
1248 }
1249 
1250 void
1252 {
1253  NS_LOG_FUNCTION (this << delBaHdr << recipient);
1254  NS_LOG_DEBUG ("received DELBA frame from=" << recipient);
1255  m_baManager->DestroyAgreement (recipient, delBaHdr->GetTid ());
1256 }
1257 
1258 void
1259 QosTxop::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, WifiMode txMode, double dataSnr)
1260 {
1261  NS_LOG_FUNCTION (this << blockAck << recipient << rxSnr << txMode.GetUniqueName () << dataSnr);
1262  NS_LOG_DEBUG ("got block ack from=" << recipient);
1263  m_baManager->NotifyGotBlockAck (blockAck, recipient, rxSnr, txMode, dataSnr);
1264  if (!m_txOkCallback.IsNull ())
1265  {
1267  }
1268  m_currentPacket = 0;
1269  ResetCw ();
1270  if (!HasTxop ())
1271  {
1273  {
1275  }
1276  m_cwTrace = GetCw ();
1277  m_backoffTrace = m_rng->GetInteger (0, GetCw ());
1280  }
1281 }
1282 
1283 void
1285 {
1286  NS_LOG_FUNCTION (this);
1287  uint8_t tid = m_currentHdr.GetQosTid ();
1288  Mac48Address recipient = m_currentHdr.GetAddr1 ();
1289  uint16_t sequence = m_currentHdr.GetSequenceNumber ();
1290  if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::INACTIVE))
1291  {
1292  m_baManager->SwitchToBlockAckIfNeeded (recipient, tid, sequence);
1293  }
1294  if ((m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED))
1295  && (GetMpduAggregator () == 0 || GetMpduAggregator ()->GetMaxAmpduSize () == 0))
1296  {
1298  }
1299 }
1300 
1302 {
1303  NS_LOG_FUNCTION (this << dest);
1304  if (m_aMpduEnabled.find (dest) != m_aMpduEnabled.end ())
1305  {
1306  return m_aMpduEnabled.find (dest)->second;
1307  }
1308  return false;
1309 }
1310 
1311 void QosTxop::SetAmpduExist (Mac48Address dest, bool enableAmpdu)
1312 {
1313  NS_LOG_FUNCTION (this << dest << enableAmpdu);
1314  if (m_aMpduEnabled.find (dest) != m_aMpduEnabled.end () && m_aMpduEnabled.find (dest)->second != enableAmpdu)
1315  {
1316  m_aMpduEnabled.erase (m_aMpduEnabled.find (dest));
1317  }
1318  if (m_aMpduEnabled.find (dest) == m_aMpduEnabled.end ())
1319  {
1320  m_aMpduEnabled.insert (std::make_pair (dest, enableAmpdu));
1321  }
1322 }
1323 
1324 void
1326 {
1327  NS_LOG_FUNCTION (this);
1329  {
1330  if (!m_currentHdr.IsRetry ())
1331  {
1333  }
1334  m_baManager->NotifyMpduTransmission (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid (),
1337  }
1338 }
1339 
1340 void
1342 {
1343  NS_ASSERT (hdr.IsQosData ());
1344  m_baManager->StorePacket (packet, hdr, tstamp);
1345  m_baManager->NotifyMpduTransmission (hdr.GetAddr1 (), hdr.GetQosTid (),
1348 }
1349 
1350 bool
1352 {
1353  NS_LOG_FUNCTION (this);
1354  uint8_t tid = m_currentHdr.GetQosTid ();
1355  Mac48Address recipient = m_currentHdr.GetAddr1 ();
1356  uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, recipient);
1357  if ((GetBlockAckThreshold () > 0 && packets >= GetBlockAckThreshold ())
1358  || (m_mpduAggregator != 0 && m_mpduAggregator->GetMaxAmpduSize () > 0 && packets > 1)
1361  {
1362  /* Block ack setup */
1363  uint16_t startingSequence = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
1364  SendAddBaRequest (recipient, tid, startingSequence, m_blockAckInactivityTimeout, true);
1365  return true;
1366  }
1367  return false;
1368 }
1369 
1370 void
1372 {
1373  NS_LOG_FUNCTION (this << &bar);
1374  WifiMacHeader hdr;
1376  hdr.SetAddr1 (bar.recipient);
1377  hdr.SetAddr2 (m_low->GetAddress ());
1378  hdr.SetAddr3 (m_low->GetBssid ());
1379  hdr.SetDsNotTo ();
1380  hdr.SetDsNotFrom ();
1381  hdr.SetNoRetry ();
1382  hdr.SetNoMoreFragments ();
1383 
1384  m_currentPacket = bar.bar;
1385  m_currentHdr = hdr;
1386 
1389  if (bar.immediate)
1390  {
1392  {
1394  }
1396  {
1398  }
1399  else if (m_blockAckType == MULTI_TID_BLOCK_ACK)
1400  {
1401  NS_FATAL_ERROR ("Multi-tid block ack is not supported");
1402  }
1403  }
1404  else
1405  {
1406  //Delayed block ack
1408  }
1410 }
1411 
1412 void
1414 {
1415  NS_LOG_FUNCTION (this);
1416  m_baManager->SetTxMiddle (m_txMiddle);
1417  m_low->RegisterEdcaForAc (m_ac, this);
1418  m_baManager->SetBlockAckInactivityCallback (MakeCallback (&QosTxop::SendDelbaFrame, this));
1419 }
1420 
1421 void
1423 {
1424  NS_LOG_FUNCTION (this << +threshold);
1425  m_blockAckThreshold = threshold;
1426  m_baManager->SetBlockAckThreshold (threshold);
1427 }
1428 
1429 void
1431 {
1432  NS_LOG_FUNCTION (this << timeout);
1434 }
1435 
1436 uint8_t
1438 {
1439  NS_LOG_FUNCTION (this);
1440  return m_blockAckThreshold;
1441 }
1442 
1443 void
1444 QosTxop::SendAddBaRequest (Mac48Address dest, uint8_t tid, uint16_t startSeq,
1445  uint16_t timeout, bool immediateBAck)
1446 {
1447  NS_LOG_FUNCTION (this << dest << +tid << startSeq << timeout << immediateBAck);
1448  NS_LOG_DEBUG ("sent ADDBA request to " << dest);
1449  WifiMacHeader hdr;
1451  hdr.SetAddr1 (dest);
1452  hdr.SetAddr2 (m_low->GetAddress ());
1453  hdr.SetAddr3 (m_low->GetAddress ());
1454  hdr.SetDsNotTo ();
1455  hdr.SetDsNotFrom ();
1456 
1457  WifiActionHeader actionHdr;
1460  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1461 
1462  Ptr<Packet> packet = Create<Packet> ();
1463  /*Setting ADDBARequest header*/
1464  MgtAddBaRequestHeader reqHdr;
1465  reqHdr.SetAmsduSupport (true);
1466  if (immediateBAck)
1467  {
1468  reqHdr.SetImmediateBlockAck ();
1469  }
1470  else
1471  {
1472  reqHdr.SetDelayedBlockAck ();
1473  }
1474  reqHdr.SetTid (tid);
1475  /* For now we don't use buffer size field in the ADDBA request frame. The recipient
1476  * will choose how many packets it can receive under block ack.
1477  */
1478  reqHdr.SetBufferSize (0);
1479  reqHdr.SetTimeout (timeout);
1480  reqHdr.SetStartingSequence (startSeq);
1481 
1482  m_baManager->CreateAgreement (&reqHdr, dest);
1483 
1484  packet->AddHeader (reqHdr);
1485  packet->AddHeader (actionHdr);
1486 
1487  m_currentPacket = packet;
1488  m_currentHdr = hdr;
1489 
1490  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
1491  m_currentHdr.SetSequenceNumber (sequence);
1496 
1500 
1502 }
1503 
1504 void
1505 QosTxop::SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator)
1506 {
1507  NS_LOG_FUNCTION (this << addr << +tid << byOriginator);
1508  WifiMacHeader hdr;
1510  hdr.SetAddr1 (addr);
1511  hdr.SetAddr2 (m_low->GetAddress ());
1512  hdr.SetAddr3 (m_low->GetAddress ());
1513  hdr.SetDsNotTo ();
1514  hdr.SetDsNotFrom ();
1515 
1516  MgtDelBaHeader delbaHdr;
1517  delbaHdr.SetTid (tid);
1518  if (byOriginator)
1519  {
1520  delbaHdr.SetByOriginator ();
1521  m_baManager->DestroyAgreement (addr, tid);
1522  }
1523  else
1524  {
1525  delbaHdr.SetByRecipient ();
1526  m_low->DestroyBlockAckAgreement (addr, tid);
1527  }
1528 
1529  WifiActionHeader actionHdr;
1532  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1533 
1534  Ptr<Packet> packet = Create<Packet> ();
1535  packet->AddHeader (delbaHdr);
1536  packet->AddHeader (actionHdr);
1537 
1538  PushFront (packet, hdr);
1539 }
1540 
1541 void
1543 {
1544  NS_LOG_FUNCTION (this);
1545  ResetCw ();
1546  m_cwTrace = GetCw ();
1547  m_backoffTrace = m_rng->GetInteger (0, GetCw ());
1549 }
1550 
1551 void
1553 {
1554  NS_LOG_FUNCTION (this << hdr);
1555  if (!m_txOkCallback.IsNull ())
1556  {
1558  }
1559 }
1560 
1561 void
1563 {
1564  NS_LOG_FUNCTION (this << hdr);
1565  if (!m_txFailedCallback.IsNull ())
1566  {
1568  }
1569 }
1570 
1571 bool
1573 {
1574  return true;
1575 }
1576 
1577 } //namespace ns3
1578 
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:540
TxFailed m_txFailedCallback
the transmit failed callback
Definition: txop.h:498
void SetRetry(void)
Set the Retry bit in the Frame Control field.
void MissedAck(void)
Event handler when an ACK is missed.
Definition: qos-txop.cc:557
void SetMoreFragments(void)
Set the More Fragment bit in the Frame Control field.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
TypeOfStation GetTypeOfStation(void) const
Return type of station.
Definition: qos-txop.cc:136
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
Ptr< MacTxMiddle > m_txMiddle
the MacTxMiddle
Definition: txop.h:501
uint32_t GetFragmentOffset(void) const
Calculate the offset for the current fragment.
Definition: qos-txop.cc:1113
void VerifyBlockAck(void)
Verifies if dequeued packet has to be transmitted with ack policy Block Ack.
Definition: qos-txop.cc:1284
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
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
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
void ReportDataFailed(Mac48Address address, const WifiMacHeader *header)
Should be invoked whenever the AckTimeout associated to a transmission attempt expires.
Mac48Address MapDestAddressForAggregation(const WifiMacHeader &hdr)
This functions are used only to correctly set destination address in A-MSDU subframes.
Definition: qos-txop.cc:1189
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 IsZero(void) const
Definition: nstime.h:288
bool IsAction() const
Return true if the header is an Action header.
bool SetupBlockAckIfNeeded()
If number of packets in the queue reaches m_blockAckThreshold value, an ADDBA Request frame is sent t...
Definition: qos-txop.cc:1351
bool GetQosSupported(Mac48Address address) const
Return whether the given station is QoS capable.
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:90
Mac48Address GetBssid(void) const
Return the Basic Service Set Identification.
Definition: mac-low.cc:426
Mac48Address GetAddr3(void) const
Return the address in the Address 3 field.
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
bool GetBaAgreementExists(Mac48Address address, uint8_t tid) const
Definition: qos-txop.cc:109
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1270
Time CalculateOverallTxTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &params, uint32_t fragmentSize=0) const
Definition: mac-low.cc:1181
#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:202
uint32_t GetNextTxopFragmentSize(uint32_t fragmentNumber) const
Calculate the size of the next TXOP fragment.
Definition: qos-txop.cc:1064
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:831
bool IsBroadcast(void) const
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:1430
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:1505
#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 IsBlockAck(void) const
Return true if the header is a Block ACK header.
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:1251
void UpdateFragmentationThreshold(void)
Typically called to update the fragmentation threshold at the start of a new transmission.
bool IsLastFragment(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, uint32_t fragmentNumber)
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:1166
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
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
bool IsQosAmsdu(void) const
Check if the A-MSDU present bit is set in the QoS control field.
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.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
void SetMsduAggregator(const Ptr< MsduAggregator > aggr)
Set the aggregator used to construct A-MSDU subframes.
Definition: qos-txop.cc:1205
Ptr< MsduAggregator > GetMsduAggregator(void) const
Returns the aggregator used to construct A-MSDU subframes.
Definition: qos-txop.cc:696
Ptr< MsduAggregator > m_msduAggregator
A-MSDU aggregator.
Definition: qos-txop.h:541
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
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
uint32_t GetNTxopFragment() const
Calculate the number of TXOP fragments needed for the transmission of the current packet...
Definition: qos-txop.cc:1025
void UpdateFailedCw(void)
Update the value of the CW variable to take into account a transmission failure.
Definition: txop.cc:212
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
void DestroyBlockAckAgreement(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2156
virtual uint32_t GetInteger(void)=0
Get the next random value as an integer drawn from the distribution.
bool IsLastFragment(void) const
Check if the current fragment is the last fragment.
Definition: qos-txop.cc:1129
void ReportFinalDataFailed(Mac48Address address, const WifiMacHeader *header)
Should be invoked after calling ReportDataFailed if NeedRetransmission returns false.
uint32_t GetNextFragmentSize(void) const
Calculate the size of the next fragment.
Definition: qos-txop.cc:1098
bool immediate
immediate
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
uint8_t GetBlockAckThreshold(void) const
Return the current threshold for block ACK mechanism.
Definition: qos-txop.cc:1437
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.
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.
bool IsStrictlyPositive(void) const
Definition: nstime.h:308
uint16_t GetSequenceControl(void) const
Return the raw Sequence Control field.
void SetAmpduExist(Mac48Address dest, bool enableAmpdu)
Set indication whether A-MPDU is used to transmit data to a peer station.
Definition: qos-txop.cc:1311
void StartAccessIfNeeded(void)
Request access from DCF manager if needed.
Definition: qos-txop.cc:749
bool IsQosTxop() const
Check for QoS TXOP.
Definition: qos-txop.cc:1572
void SendBlockAckRequest(const Bar &bar)
After that all packets, for which a block ack agreement was established, have been transmitted...
Definition: qos-txop.cc:1371
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
std::string GetUniqueName(void) const
Definition: wifi-mode.cc:463
static Mac48Address GetBroadcast(void)
bool IsQosBlockAck(void) const
Return if the QoS ACK policy is Block ACK.
Headers for Block ack response.
Definition: ctrl-headers.h:181
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
Mac48Address GetAddress(void) const
Return the MAC address of this MacLow.
Definition: mac-low.cc:370
void RegisterEdcaForAc(AcIndex ac, Ptr< QosTxop > edca)
Definition: mac-low.cc:2435
TracedValue< uint32_t > m_backoffTrace
backoff trace value
Definition: qos-txop.h:555
void GotAddBaResponse(const MgtAddBaResponseHeader *respHdr, Mac48Address recipient)
Event handler when an ADDBA response is received.
Definition: qos-txop.cc:1229
void SetTypeOfStation(TypeOfStation type)
Set type of station with the given type.
Definition: qos-txop.cc:129
void MissedCts(void)
Event handler when a CTS timeout has occurred.
Definition: qos-txop.cc:428
uint32_t GetTxopFragmentOffset(uint32_t fragmentNumber) const
Calculate the offset for the fragment.
Definition: qos-txop.cc:1038
void PushFront(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Definition: qos-txop.cc:1219
Mac48Address recipient
recipient
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
void SetByOriginator(void)
Set the initiator bit in the DELBA.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
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.
bool GetAmpduExist(Mac48Address dest) const
Return whether A-MPDU is used to transmit data to a peer station.
Definition: qos-txop.cc:1301
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:1212
Every class exported by the ns3 library is enclosed in the ns3 namespace.
address
Definition: first.py:37
bool IsGroup(void) const
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:1562
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)
uint8_t GetTid(void) const
Return the Traffic ID (TID).
Ptr< WifiMacQueue > m_queue
the wifi MAC queue
Definition: txop.h:500
virtual void DoDispose(void)
Destructor implementation.
Definition: txop.cc:97
StatusCode GetStatusCode(void) const
Return the status code.
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
bool HasVhtSupported(void) const
Return whether the device has VHT capability support enabled.
bool IsByOriginator(void) const
Check if the initiator bit in the DELBA is set.
void BaTxOk(const WifiMacHeader &hdr)
The packet we sent was successfully received by the receiver.
Definition: qos-txop.cc:1552
Ptr< const Packet > m_currentPacket
the current packet
Definition: txop.h:521
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:936
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
Ptr< MpduAggregator > GetMpduAggregator(void) const
Returns the aggregator used to construct A-MPDU subframes.
Definition: qos-txop.cc:702
uint16_t PeekNextSequenceNumberFor(const WifiMacHeader *hdr)
Return the next sequence number for the Traffic ID and destination, but do not pick it (i...
void SetBlockAckThreshold(uint8_t threshold)
Set threshold for block ACK mechanism.
Definition: qos-txop.cc:1422
TracedValue< uint32_t > m_cwTrace
CW trace value.
Definition: qos-txop.h:556
uint32_t GetCw(void) const
Definition: txop.cc:199
uint8_t GetTid(void) const
Return the Traffic ID (TID).
Time GetTxopLimit(void) const
Return the TXOP limit.
Definition: txop.cc:290
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:2876
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > remoteManager)
Set WifiRemoteStationsManager this QosTxop is associated to.
Definition: qos-txop.cc:121
Ptr< MacLow > GetLow(void) const
Return the MacLow associated with this Txop.
Definition: txop.cc:339
bool HasHtSupported(void) const
Return whether the device has HT capability support enabled.
void NotifyCollision(void)
Notify the EDCAF that collision has occurred.
Definition: qos-txop.cc:419
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
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 SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
bool HasHeSupported(void) const
Return whether the device has HE capability support enabled.
uint32_t GetFragmentSize(void) const
Calculate the size of the current fragment.
Definition: qos-txop.cc:1083
bool Aggregate(Ptr< const Packet > packet, Ptr< Packet > aggregatedPacket, Mac48Address src, Mac48Address dest) const
Adds packet to aggregatedPacket.
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:1259
bool MustSendHtImmediateAck(void) const
Check if the current ACK policy is immediate.
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:491
bool IsData(void) const
Return true if the Type is DATA.
void StartNextPacket(void)
Start transmission for the next packet if allowed by the TxopLimit.
Definition: qos-txop.cc:812
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS DATA...
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.
bool IsBlockAckReq(void) const
Return true if the header is a Block ACK Request header.
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:1325
Implement the header for management frames of type add block ack response.
Definition: mgt-headers.h:1129
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:1173
Time GetTxopRemaining(void) const
Return the remaining duration in the current TXOP.
Definition: qos-txop.cc:884
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:270
WifiMacType GetType(void) const
Return the type (enum WifiMacType)
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:1007
Ptr< const Packet > bar
block ack request
Ptr< QosBlockedDestinations > m_qosBlockedDestinations
QOS blocked destinations.
Definition: qos-txop.h:544
bool IsSuccess(void) const
Return whether the status code is success.
Definition: status-code.cc:42
void NotifyAccessGranted(void)
Notify the EDCAF that access has been granted.
Definition: qos-txop.cc:166
uint16_t GetMaxAmpduSize(void) const
Returns the maximum A-MPDU size in bytes.
bool HasTxop(void) const
Check if the station has TXOP granted for the next MPDU.
Definition: qos-txop.cc:897
bool NeedFragmentation(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
bool IsStrictlyNegative(void) const
Definition: nstime.h:303
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:1341
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:1413
bool m_currentIsFragmented
flag whether current packet is fragmented
Definition: qos-txop.h:553
virtual bool IsAccessRequested(void) const
Definition: txop.cc:435
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:1542
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
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...
TypeOfStation
Enumeration for type of station.
Definition: qos-txop.h:45
bool IsTxopFragmentation() const
Check if the current packet is fragmented because of an exceeded TXOP duration.
Definition: qos-txop.cc:977
bool NeedFragmentation(void) const
Check if the current packet should be fragmented.
Definition: qos-txop.cc:953
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:1145
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
Ptr< WifiRemoteStationManager > m_stationManager
the wifi remote station manager
Definition: txop.h:503
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:329
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
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
uint16_t GetNextSeqNumberByTidAndAddress(uint8_t tid, Mac48Address addr) const
Return the next sequence number for the Traffic ID and destination.
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)
bool IsRetry(void) const
Return if the Retry bit is set.
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
uint32_t GetTxopFragmentSize() const
Calculate the size of the current TXOP fragment.
Definition: qos-txop.cc:992
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.
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:1444
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 GetSequenceNumber(void) const
Return the sequence number of the header.
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
void SetQosAckPolicy(QosAckPolicy policy)
Set the QoS ACK policy in the QoS control field.