A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
edca-txop-n.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  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  * Author: Mirko Banchi <mk.banchi@gmail.com>
21  */
22 #include "ns3/log.h"
23 #include "ns3/assert.h"
24 #include "ns3/pointer.h"
25 
26 #include "edca-txop-n.h"
27 #include "mac-low.h"
28 #include "dcf-manager.h"
29 #include "mac-tx-middle.h"
30 #include "wifi-mac-trailer.h"
31 #include "wifi-mac.h"
32 #include "random-stream.h"
33 #include "wifi-mac-queue.h"
34 #include "msdu-aggregator.h"
35 #include "mgt-headers.h"
37 
38 NS_LOG_COMPONENT_DEFINE ("EdcaTxopN");
39 
40 #undef NS_LOG_APPEND_CONTEXT
41 #define NS_LOG_APPEND_CONTEXT if (m_low != 0) { std::clog << "[mac=" << m_low->GetAddress () << "] "; }
42 
43 namespace ns3 {
44 
45 class EdcaTxopN::Dcf : public DcfState
46 {
47 public:
48  Dcf (EdcaTxopN * txop)
49  : m_txop (txop)
50  {
51  }
52 private:
53  virtual void DoNotifyAccessGranted (void)
54  {
56  }
57  virtual void DoNotifyInternalCollision (void)
58  {
60  }
61  virtual void DoNotifyCollision (void)
62  {
64  }
65  virtual void DoNotifyChannelSwitching (void)
66  {
68  }
70 };
71 
73 {
74 public:
77  m_txop (txop) {
78  }
79 
80  virtual ~TransmissionListener () {}
81 
82  virtual void GotCts (double snr, WifiMode txMode)
83  {
84  m_txop->GotCts (snr, txMode);
85  }
86  virtual void MissedCts (void)
87  {
88  m_txop->MissedCts ();
89  }
90  virtual void GotAck (double snr, WifiMode txMode)
91  {
92  m_txop->GotAck (snr, txMode);
93  }
94  virtual void MissedAck (void)
95  {
96  m_txop->MissedAck ();
97  }
98  virtual void GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address source)
99  {
100  m_txop->GotBlockAck (blockAck, source);
101  }
102  virtual void MissedBlockAck (void)
103  {
105  }
106  virtual void StartNext (void)
107  {
108  m_txop->StartNext ();
109  }
110  virtual void Cancel (void)
111  {
112  m_txop->Cancel ();
113  }
114  virtual void EndTxNoAck (void)
115  {
116  m_txop->EndTxNoAck ();
117  }
118 
119 private:
121 };
122 
124 {
125 public:
128  m_txop (txop) {
129  }
131 
132  virtual void BlockAckInactivityTimeout (Mac48Address address, uint8_t tid)
133  {
134  m_txop->SendDelbaFrame (address, tid, false);
135  }
136 
137 private:
139 };
140 
142 
143 TypeId
145 {
146  static TypeId tid = TypeId ("ns3::EdcaTxopN")
149  .AddAttribute ("BlockAckThreshold", "If number of packets in this queue reaches this value,\
150  block ack mechanism is used. If this value is 0, block ack is never used.",
151  UintegerValue (0),
152  MakeUintegerAccessor (&EdcaTxopN::SetBlockAckThreshold,
154  MakeUintegerChecker<uint8_t> (0, 64))
155  .AddAttribute ("BlockAckInactivityTimeout", "Represents max time (blocks of 1024 micro seconds) allowed for block ack\
156  inactivity. If this value isn't equal to 0 a timer start after that a\
157  block ack setup is completed and will be reset every time that a block\
158  ack frame is received. If this value is 0, block ack inactivity timeout won't be used.",
159  UintegerValue (0),
160  MakeUintegerAccessor (&EdcaTxopN::SetBlockAckInactivityTimeout),
161  MakeUintegerChecker<uint16_t> ())
162  .AddAttribute ("Queue", "The WifiMacQueue object",
163  PointerValue (),
164  MakePointerAccessor (&EdcaTxopN::GetQueue),
165  MakePointerChecker<WifiMacQueue> ())
166  ;
167  return tid;
168 }
169 
171  : m_manager (0),
172  m_currentPacket (0),
173  m_aggregator (0),
174  m_blockAckType (COMPRESSED_BLOCK_ACK)
175 {
176  NS_LOG_FUNCTION (this);
179  m_dcf = new EdcaTxopN::Dcf (this);
180  m_queue = CreateObject<WifiMacQueue> ();
181  m_rng = new RealRandomStream ();
183  m_baManager = new BlockAckManager ();
189 }
190 
192 {
193  NS_LOG_FUNCTION (this);
194 }
195 
196 void
198 {
199  NS_LOG_FUNCTION (this);
200  m_queue = 0;
201  m_low = 0;
202  m_stationManager = 0;
203  delete m_transmissionListener;
204  delete m_dcf;
205  delete m_rng;
207  delete m_baManager;
208  delete m_blockAckListener;
210  m_dcf = 0;
211  m_rng = 0;
213  m_baManager = 0;
214  m_blockAckListener = 0;
215  m_txMiddle = 0;
216  m_aggregator = 0;
217 }
218 
219 void
221 {
222  NS_LOG_FUNCTION (this << manager);
223  m_manager = manager;
224  m_manager->Add (m_dcf);
225 }
226 
227 void
229 {
230  m_txOkCallback = callback;
231 }
232 
233 void
235 {
236  m_txFailedCallback = callback;
237 }
238 
239 void
241 {
242  NS_LOG_FUNCTION (this << remoteManager);
243  m_stationManager = remoteManager;
244 }
245 void
247 {
248  NS_LOG_FUNCTION (this << type);
249  m_typeOfStation = type;
250 }
251 
252 enum TypeOfStation
254 {
255  return m_typeOfStation;
256 }
257 
260 {
261  NS_LOG_FUNCTION (this);
262  return m_queue;
263 }
264 
265 void
266 EdcaTxopN::SetMinCw (uint32_t minCw)
267 {
268  NS_LOG_FUNCTION (this << minCw);
269  m_dcf->SetCwMin (minCw);
270 }
271 
272 void
273 EdcaTxopN::SetMaxCw (uint32_t maxCw)
274 {
275  NS_LOG_FUNCTION (this << maxCw);
276  m_dcf->SetCwMax (maxCw);
277 }
278 
279 void
280 EdcaTxopN::SetAifsn (uint32_t aifsn)
281 {
282  NS_LOG_FUNCTION (this << aifsn);
283  m_dcf->SetAifsn (aifsn);
284 }
285 
286 uint32_t
288 {
289  return m_dcf->GetCwMin ();
290 }
291 
292 uint32_t
294 {
295  return m_dcf->GetCwMax ();
296 }
297 
298 uint32_t
300 {
301  return m_dcf->GetAifsn ();
302 }
303 
304 void
306 {
307  m_txMiddle = txMiddle;
308 }
309 
312 {
313  return m_low;
314 }
315 
316 void
318 {
319  NS_LOG_FUNCTION (this << low);
320  m_low = low;
321 }
322 
323 bool
325 {
326  return !m_queue->IsEmpty () || m_currentPacket != 0 || m_baManager->HasPackets ();
327 }
328 
329 void
331 {
332  NS_LOG_FUNCTION (this);
333  if (m_currentPacket == 0)
334  {
335  if (m_queue->IsEmpty () && !m_baManager->HasPackets ())
336  {
337  NS_LOG_DEBUG ("queue is empty");
338  return;
339  }
341  {
343  return;
344  }
345  /* check if packets need retransmission are stored in BlockAckManager */
347  if (m_currentPacket == 0)
348  {
350  {
351  NS_LOG_DEBUG ("no available packets in the queue");
352  return;
353  }
355  && m_blockAckThreshold > 0
357  && SetupBlockAckIfNeeded ())
358  {
359  return;
360  }
362  NS_ASSERT (m_currentPacket != 0);
363 
364  uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHdr);
365  m_currentHdr.SetSequenceNumber (sequence);
369  m_fragmentNumber = 0;
370  NS_LOG_DEBUG ("dequeued size=" << m_currentPacket->GetSize () <<
371  ", to=" << m_currentHdr.GetAddr1 () <<
372  ", seq=" << m_currentHdr.GetSequenceControl ());
374  {
375  VerifyBlockAck ();
376  }
377  }
378  }
380  params.DisableOverrideDurationId ();
381  if (m_currentHdr.GetAddr1 ().IsGroup ())
382  {
383  params.DisableRts ();
384  params.DisableAck ();
385  params.DisableNextData ();
387  &m_currentHdr,
388  params,
390 
391  NS_LOG_DEBUG ("tx broadcast");
392  }
394  {
396  }
397  else
398  {
400  {
401  params.DisableAck ();
402  }
403  else
404  {
405  params.EnableAck ();
406  }
408  && !m_currentHdr.IsQosAmsdu ())
409  || m_currentHdr.IsData ())
410  && (m_blockAckThreshold == 0
412  {
413  //With COMPRESSED_BLOCK_ACK fragmentation must be avoided.
414  params.DisableRts ();
415  WifiMacHeader hdr;
416  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
417  if (IsLastFragment ())
418  {
419  NS_LOG_DEBUG ("fragmenting last fragment size=" << fragment->GetSize ());
420  params.DisableNextData ();
421  }
422  else
423  {
424  NS_LOG_DEBUG ("fragmenting size=" << fragment->GetSize ());
426  }
427  m_low->StartTransmission (fragment, &hdr, params,
429  }
430  else
431  {
432  WifiMacHeader peekedHdr;
433  if (m_currentHdr.IsQosData ()
437  && m_aggregator != 0 && !m_currentHdr.IsRetry ())
438  {
439  /* here is performed aggregation */
440  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
441  m_aggregator->Aggregate (m_currentPacket, currentAggregatedPacket,
442  MapSrcAddressForAggregation (peekedHdr),
443  MapDestAddressForAggregation (peekedHdr));
444  bool aggregated = false;
445  bool isAmsdu = false;
446  Ptr<const Packet> peekedPacket = m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (),
449  while (peekedPacket != 0)
450  {
451  aggregated = m_aggregator->Aggregate (peekedPacket, currentAggregatedPacket,
452  MapSrcAddressForAggregation (peekedHdr),
453  MapDestAddressForAggregation (peekedHdr));
454  if (aggregated)
455  {
456  isAmsdu = true;
457  m_queue->Remove (peekedPacket);
458  }
459  else
460  {
461  break;
462  }
463  peekedPacket = m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (),
465  }
466  if (isAmsdu)
467  {
470  m_currentPacket = currentAggregatedPacket;
471  currentAggregatedPacket = 0;
472  NS_LOG_DEBUG ("tx unicast A-MSDU");
473  }
474  }
475  if (NeedRts ())
476  {
477  params.EnableRts ();
478  NS_LOG_DEBUG ("tx unicast rts");
479  }
480  else
481  {
482  params.DisableRts ();
483  NS_LOG_DEBUG ("tx unicast");
484  }
485  params.DisableNextData ();
487  params, m_transmissionListener);
488  CompleteTx ();
489  }
490  }
491 }
492 
494 {
495  NS_LOG_FUNCTION (this);
496  NotifyCollision ();
497 }
498 
499 void
501 {
502  NS_LOG_FUNCTION (this);
505 }
506 
507 void
508 EdcaTxopN::GotCts (double snr, WifiMode txMode)
509 {
510  NS_LOG_FUNCTION (this << snr << txMode);
511  NS_LOG_DEBUG ("got cts");
512 }
513 
514 void
516 {
517  NS_LOG_FUNCTION (this);
518  NS_LOG_DEBUG ("missed cts");
519  if (!NeedRtsRetransmission ())
520  {
521  NS_LOG_DEBUG ("Cts Fail");
523  if (!m_txFailedCallback.IsNull ())
524  {
526  }
527  // to reset the dcf.
528  m_currentPacket = 0;
529  m_dcf->ResetCw ();
530  }
531  else
532  {
533  m_dcf->UpdateFailedCw ();
534  }
537 }
538 
539 void
541 {
542  m_queue->Flush ();
543  m_currentPacket = 0;
544 }
545 
546 void
548 {
549  NS_LOG_FUNCTION (this << packet << &hdr);
550  WifiMacTrailer fcs;
551  uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.GetSerializedSize ();
553  packet, fullPacketSize);
554  m_queue->Enqueue (packet, hdr);
556 }
557 
558 void
559 EdcaTxopN::GotAck (double snr, WifiMode txMode)
560 {
561  NS_LOG_FUNCTION (this << snr << txMode);
562  if (!NeedFragmentation ()
563  || IsLastFragment ()
564  || m_currentHdr.IsQosAmsdu ())
565  {
566  NS_LOG_DEBUG ("got ack. tx done.");
567  if (!m_txOkCallback.IsNull ())
568  {
570  }
571 
572  if (m_currentHdr.IsAction ())
573  {
574  WifiActionHeader actionHdr;
576  p->RemoveHeader (actionHdr);
577  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK
579  {
580  MgtDelBaHeader delBa;
581  p->PeekHeader (delBa);
582  if (delBa.IsByOriginator ())
583  {
585  }
586  else
587  {
589  }
590  }
591  }
592  m_currentPacket = 0;
593 
594  m_dcf->ResetCw ();
597  }
598  else
599  {
600  NS_LOG_DEBUG ("got ack. tx not done, size=" << m_currentPacket->GetSize ());
601  }
602 }
603 
604 void
606 {
607  NS_LOG_FUNCTION (this);
608  NS_LOG_DEBUG ("missed ack");
609  if (!NeedDataRetransmission ())
610  {
611  NS_LOG_DEBUG ("Ack Fail");
613  if (!m_txFailedCallback.IsNull ())
614  {
616  }
617  // to reset the dcf.
618  m_currentPacket = 0;
619  m_dcf->ResetCw ();
620  }
621  else
622  {
623  NS_LOG_DEBUG ("Retransmit");
625  m_dcf->UpdateFailedCw ();
626  }
629 }
630 
631 void
633 {
634  NS_LOG_FUNCTION (this);
635  NS_LOG_DEBUG ("missed block ack");
636  //should i report this to station addressed by ADDR1?
637  NS_LOG_DEBUG ("Retransmit block ack request");
639  m_dcf->UpdateFailedCw ();
640 
643 }
644 
647 {
648  return m_aggregator;
649 }
650 
651 void
653 {
654  NS_LOG_FUNCTION (this);
655  if ((m_currentPacket != 0
656  || !m_queue->IsEmpty () || m_baManager->HasPackets ())
657  && !m_dcf->IsAccessRequested ())
658  {
660  }
661 }
662 
663 void
665 {
666  NS_LOG_FUNCTION (this);
667  if (m_currentPacket == 0
668  && (!m_queue->IsEmpty () || m_baManager->HasPackets ())
669  && !m_dcf->IsAccessRequested ())
670  {
672  }
673 }
674 
675 bool
677 {
680 }
681 
682 bool
684 {
687 }
688 
689 bool
691 {
694 }
695 
696 void
698 {
700 }
701 
702 void
704 {
705  NS_LOG_FUNCTION (this);
706  NS_LOG_DEBUG ("start next packet fragment");
707  /* this callback is used only for fragments. */
708  NextFragment ();
709  WifiMacHeader hdr;
710  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
712  params.EnableAck ();
713  params.DisableRts ();
714  params.DisableOverrideDurationId ();
715  if (IsLastFragment ())
716  {
717  params.DisableNextData ();
718  }
719  else
720  {
722  }
723  Low ()->StartTransmission (fragment, &hdr, params, m_transmissionListener);
724 }
725 
726 void
728 {
729  NS_LOG_FUNCTION (this);
730  NS_LOG_DEBUG ("transmission cancelled");
731 }
732 
733 void
735 {
736  NS_LOG_FUNCTION (this);
737  NS_LOG_DEBUG ("a transmission that did not require an ACK just finished");
738  m_currentPacket = 0;
739  m_dcf->ResetCw ();
742 }
743 
744 bool
746 {
749 }
750 
751 uint32_t
753 {
756 }
757 
758 uint32_t
760 {
763 }
764 
765 uint32_t
767 {
770 }
771 
772 
773 bool
775 {
778 }
779 
782 {
783  *hdr = m_currentHdr;
785  uint32_t startOffset = GetFragmentOffset ();
786  Ptr<Packet> fragment;
787  if (IsLastFragment ())
788  {
789  hdr->SetNoMoreFragments ();
790  }
791  else
792  {
793  hdr->SetMoreFragments ();
794  }
795  fragment = m_currentPacket->CreateFragment (startOffset,
796  GetFragmentSize ());
797  return fragment;
798 }
799 
800 void
802 {
803  m_ac = ac;
804 }
805 
808 {
809  Mac48Address retval;
811  {
812  retval = hdr.GetAddr2 ();
813  }
814  else
815  {
816  retval = hdr.GetAddr3 ();
817  }
818  return retval;
819 }
820 
823 {
824  Mac48Address retval;
826  {
827  retval = hdr.GetAddr1 ();
828  }
829  else
830  {
831  retval = hdr.GetAddr3 ();
832  }
833  return retval;
834 }
835 
836 void
838 {
839  m_aggregator = aggr;
840 }
841 
842 void
844 {
845  NS_LOG_FUNCTION (this << packet << &hdr);
846  WifiMacTrailer fcs;
847  uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.GetSerializedSize ();
849  packet, fullPacketSize);
850  m_queue->PushFront (packet, hdr);
852 }
853 
854 void
856 {
857  NS_LOG_FUNCTION (this);
858  NS_LOG_DEBUG ("received ADDBA response from " << recipient);
859  uint8_t tid = respHdr->GetTid ();
861  {
862  if (respHdr->GetStatusCode ().IsSuccess ())
863  {
864  NS_LOG_DEBUG ("block ack agreement established with " << recipient);
865  m_baManager->UpdateAgreement (respHdr, recipient);
866  }
867  else
868  {
869  NS_LOG_DEBUG ("discard ADDBA response" << recipient);
870  m_baManager->NotifyAgreementUnsuccessful (recipient, tid);
871  }
872  }
874 }
875 
876 void
878 {
879  NS_LOG_FUNCTION (this);
880  NS_LOG_DEBUG ("received DELBA frame from=" << recipient);
881  m_baManager->TearDownBlockAck (recipient, delBaHdr->GetTid ());
882 }
883 
884 void
886 {
887  NS_LOG_DEBUG ("got block ack from=" << recipient);
888  m_baManager->NotifyGotBlockAck (blockAck, recipient);
889  m_currentPacket = 0;
890  m_dcf->ResetCw ();
893 }
894 
895 void
897 {
898  NS_LOG_FUNCTION (this);
899  uint8_t tid = m_currentHdr.GetQosTid ();
900  Mac48Address recipient = m_currentHdr.GetAddr1 ();
901  uint16_t sequence = m_currentHdr.GetSequenceNumber ();
903  {
904  m_baManager->SwitchToBlockAckIfNeeded (recipient, tid, sequence);
905  }
907  {
909  }
910 }
911 
912 void
914 {
916  {
917  if (!m_currentHdr.IsRetry ())
918  {
920  }
923  m_currentHdr.GetAddr1 ()));
924  //we are not waiting for an ack: transmission is completed
925  m_currentPacket = 0;
926  m_dcf->ResetCw ();
929  }
930 }
931 
932 bool
934 {
935  uint8_t tid = m_currentHdr.GetQosTid ();
936  Mac48Address recipient = m_currentHdr.GetAddr1 ();
937 
938  uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, WifiMacHeader::ADDR1, recipient);
939 
940  if (packets >= m_blockAckThreshold)
941  {
942  /* Block ack setup */
943  uint16_t startingSequence = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
944  SendAddBaRequest (recipient, tid, startingSequence, m_blockAckInactivityTimeout, true);
945  return true;
946  }
947  return false;
948 }
949 
950 void
952 {
953  NS_LOG_FUNCTION (this);
954  WifiMacHeader hdr;
956  hdr.SetAddr1 (bar.recipient);
957  hdr.SetAddr2 (m_low->GetAddress ());
958  hdr.SetAddr3 (m_low->GetBssid ());
959  hdr.SetDsNotTo ();
960  hdr.SetDsNotFrom ();
961  hdr.SetNoRetry ();
962  hdr.SetNoMoreFragments ();
963 
964  m_currentPacket = bar.bar;
965  m_currentHdr = hdr;
966 
968  params.DisableRts ();
969  params.DisableNextData ();
970  params.DisableOverrideDurationId ();
971  if (bar.immediate)
972  {
974  {
975  params.EnableBasicBlockAck ();
976  }
978  {
979  params.EnableCompressedBlockAck ();
980  }
982  {
983  NS_FATAL_ERROR ("Multi-tid block ack is not supported");
984  }
985  }
986  else
987  {
988  //Delayed block ack
989  params.EnableAck ();
990  }
992 }
993 
994 void
996 {
997  NS_LOG_FUNCTION (this);
1001 }
1002 
1003 void
1005 {
1006  m_blockAckThreshold = threshold;
1007  m_baManager->SetBlockAckThreshold (threshold);
1008 }
1009 
1010 void
1012 {
1014 }
1015 
1016 uint8_t
1018 {
1019  return m_blockAckThreshold;
1020 }
1021 
1022 void
1023 EdcaTxopN::SendAddBaRequest (Mac48Address dest, uint8_t tid, uint16_t startSeq,
1024  uint16_t timeout, bool immediateBAck)
1025 {
1026  NS_LOG_FUNCTION (this);
1027  NS_LOG_DEBUG ("sent ADDBA request to " << dest);
1028  WifiMacHeader hdr;
1029  hdr.SetAction ();
1030  hdr.SetAddr1 (dest);
1031  hdr.SetAddr2 (m_low->GetAddress ());
1032  hdr.SetAddr3 (m_low->GetAddress ());
1033  hdr.SetDsNotTo ();
1034  hdr.SetDsNotFrom ();
1035 
1036  WifiActionHeader actionHdr;
1039  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1040 
1041  Ptr<Packet> packet = Create<Packet> ();
1042  /*Setting ADDBARequest header*/
1043  MgtAddBaRequestHeader reqHdr;
1044  reqHdr.SetAmsduSupport (true);
1045  if (immediateBAck)
1046  {
1047  reqHdr.SetImmediateBlockAck ();
1048  }
1049  else
1050  {
1051  reqHdr.SetDelayedBlockAck ();
1052  }
1053  reqHdr.SetTid (tid);
1054  /* For now we don't use buffer size field in the ADDBA request frame. The recipient
1055  * will choose how many packets it can receive under block ack.
1056  */
1057  reqHdr.SetBufferSize (0);
1058  reqHdr.SetTimeout (timeout);
1059  reqHdr.SetStartingSequence (startSeq);
1060 
1061  m_baManager->CreateAgreement (&reqHdr, dest);
1062 
1063  packet->AddHeader (reqHdr);
1064  packet->AddHeader (actionHdr);
1065 
1066  m_currentPacket = packet;
1067  m_currentHdr = hdr;
1068 
1069  uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHdr);
1070  m_currentHdr.SetSequenceNumber (sequence);
1074 
1076  params.EnableAck ();
1077  params.DisableRts ();
1078  params.DisableNextData ();
1079  params.DisableOverrideDurationId ();
1080 
1083 }
1084 
1085 void
1086 EdcaTxopN::SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator)
1087 {
1088  WifiMacHeader hdr;
1089  hdr.SetAction ();
1090  hdr.SetAddr1 (addr);
1091  hdr.SetAddr2 (m_low->GetAddress ());
1092  hdr.SetAddr3 (m_low->GetAddress ());
1093  hdr.SetDsNotTo ();
1094  hdr.SetDsNotFrom ();
1095 
1096  MgtDelBaHeader delbaHdr;
1097  delbaHdr.SetTid (tid);
1098  if (byOriginator)
1099  {
1100  delbaHdr.SetByOriginator ();
1101  }
1102  else
1103  {
1104  delbaHdr.SetByRecipient ();
1105  }
1106 
1107  WifiActionHeader actionHdr;
1110  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1111 
1112  Ptr<Packet> packet = Create<Packet> ();
1113  packet->AddHeader (delbaHdr);
1114  packet->AddHeader (actionHdr);
1115 
1116  PushFront (packet, hdr);
1117 }
1118 
1119 int64_t
1121 {
1122  NS_LOG_FUNCTION (this << stream);
1123  m_rng->AssignStreams (stream);
1124  return 1;
1125 }
1126 
1127 void
1129 {
1130  m_dcf->ResetCw ();
1132  ns3::Dcf::DoStart ();
1133 }
1134 } // namespace ns3