A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
edca-txop-n.cc
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"
36 #include "qos-blocked-destinations.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  {
55  m_txop->NotifyAccessGranted ();
56  }
57  virtual void DoNotifyInternalCollision (void)
58  {
59  m_txop->NotifyInternalCollision ();
60  }
61  virtual void DoNotifyCollision (void)
62  {
63  m_txop->NotifyCollision ();
64  }
65  virtual void DoNotifyChannelSwitching (Time duration, uint16_t toChannel)
66  {
67  m_txop->NotifyChannelSwitching (duration);
68  }
69  virtual void DoNotifyChannelSensing (void)
70  {
71  m_txop->NotifyChannelSensing ();
72  }
73  EdcaTxopN *m_txop;
74 };
75 
77 {
78 public:
81  m_txop (txop) {
82  }
83 
84  virtual ~TransmissionListener () {}
85 
86  virtual void GotCts (double snr, WifiMode txMode)
87  {
88  m_txop->GotCts (snr, txMode);
89  }
90  virtual void MissedCts (void)
91  {
92  m_txop->MissedCts ();
93  }
94  virtual void GotAck (double snr, WifiMode txMode)
95  {
96  m_txop->GotAck (snr, txMode);
97  }
98  virtual void MissedAck (void)
99  {
100  m_txop->MissedAck ();
101  }
102  virtual void GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address source)
103  {
104  m_txop->GotBlockAck (blockAck, source);
105  }
106  virtual void MissedBlockAck (void)
107  {
108  m_txop->MissedBlockAck ();
109  }
110  virtual void StartNext (void)
111  {
112  m_txop->StartNext ();
113  }
114  virtual void Cancel (void)
115  {
116  m_txop->Cancel ();
117  }
118  virtual void EndTxNoAck (void)
119  {
120  m_txop->EndTxNoAck ();
121  }
122 
123 private:
124  EdcaTxopN *m_txop;
125 };
126 
128 {
129 public:
132  m_txop (txop) {
133  }
134  virtual ~BlockAckEventListener () {}
135 
136  virtual void BlockAckInactivityTimeout (Mac48Address address, uint8_t tid)
137  {
138  m_txop->SendDelbaFrame (address, tid, false);
139  }
140 
141 private:
142  EdcaTxopN *m_txop;
143 };
144 
145 NS_OBJECT_ENSURE_REGISTERED (EdcaTxopN);
146 
147 TypeId
148 EdcaTxopN::GetTypeId (void)
149 {
150  static TypeId tid = TypeId ("ns3::EdcaTxopN")
151  .SetParent (ns3::Dcf::GetTypeId ())
153  .AddAttribute ("BlockAckThreshold", "If number of packets in this queue reaches this value,\
154  block ack mechanism is used. If this value is 0, block ack is never used.",
155  UintegerValue (0),
156  MakeUintegerAccessor (&EdcaTxopN::SetBlockAckThreshold,
157  &EdcaTxopN::GetBlockAckThreshold),
158  MakeUintegerChecker<uint8_t> (0, 64))
159  .AddAttribute ("BlockAckInactivityTimeout", "Represents max time (blocks of 1024 micro seconds) allowed for block ack\
160  inactivity. If this value isn't equal to 0 a timer start after that a\
161  block ack setup is completed and will be reset every time that a block\
162  ack frame is received. If this value is 0, block ack inactivity timeout won't be used.",
163  UintegerValue (0),
164  MakeUintegerAccessor (&EdcaTxopN::SetBlockAckInactivityTimeout),
165  MakeUintegerChecker<uint16_t> ())
166  .AddAttribute ("Queue", "The WifiMacQueue object",
167  PointerValue (),
168  MakePointerAccessor (&EdcaTxopN::GetQueue),
169  MakePointerChecker<WifiMacQueue> ())
170  ;
171  return tid;
172 }
173 
174 EdcaTxopN::EdcaTxopN ()
175  : m_manager (0),
176  m_currentPacket (0),
177  m_aggregator (0),
178  m_blockAckType (COMPRESSED_BLOCK_ACK)
179 {
180  NS_LOG_FUNCTION (this);
181  m_transmissionListener = new EdcaTxopN::TransmissionListener (this);
182  m_blockAckListener = new EdcaTxopN::BlockAckEventListener (this);
183  m_dcf = new EdcaTxopN::Dcf (this);
184  m_queue = CreateObject<WifiMacQueue> ();
185  m_rng = new RealRandomStream ();
186  m_qosBlockedDestinations = new QosBlockedDestinations ();
187  m_baManager = new BlockAckManager ();
188  m_baManager->SetQueue (m_queue);
189  m_baManager->SetBlockAckType (m_blockAckType);
190  m_baManager->SetBlockDestinationCallback (MakeCallback (&QosBlockedDestinations::Block, m_qosBlockedDestinations));
191  m_baManager->SetUnblockDestinationCallback (MakeCallback (&QosBlockedDestinations::Unblock, m_qosBlockedDestinations));
192  m_baManager->SetMaxPacketDelay (m_queue->GetMaxDelay ());
193 }
194 
195 EdcaTxopN::~EdcaTxopN ()
196 {
197  NS_LOG_FUNCTION (this);
198 }
199 
200 void
202 {
203  NS_LOG_FUNCTION (this);
204  m_queue = 0;
205  m_low = 0;
206  m_stationManager = 0;
207  delete m_transmissionListener;
208  delete m_dcf;
209  delete m_rng;
210  delete m_qosBlockedDestinations;
211  delete m_baManager;
212  delete m_blockAckListener;
213  m_transmissionListener = 0;
214  m_dcf = 0;
215  m_rng = 0;
216  m_qosBlockedDestinations = 0;
217  m_baManager = 0;
218  m_blockAckListener = 0;
219  m_txMiddle = 0;
220  m_aggregator = 0;
221 }
222 
223 void
224 EdcaTxopN::SetManager (DcfManager *manager)
225 {
226  NS_LOG_FUNCTION (this << manager);
227  m_manager = manager;
228  m_manager->Add (m_dcf);
229 }
230 
231 void
232 EdcaTxopN::SetTxOkCallback (TxOk callback)
233 {
234  NS_LOG_FUNCTION (this << &callback);
235  m_txOkCallback = callback;
236 }
237 
238 void
239 EdcaTxopN::SetTxFailedCallback (TxFailed callback)
240 {
241  NS_LOG_FUNCTION (this << &callback);
242  m_txFailedCallback = callback;
243 }
244 
245 void
246 EdcaTxopN::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> remoteManager)
247 {
248  NS_LOG_FUNCTION (this << remoteManager);
249  m_stationManager = remoteManager;
250 }
251 void
252 EdcaTxopN::SetTypeOfStation (enum TypeOfStation type)
253 {
254  NS_LOG_FUNCTION (this << static_cast<uint32_t> (type));
255  m_typeOfStation = type;
256 }
257 
258 enum TypeOfStation
259 EdcaTxopN::GetTypeOfStation (void) const
260 {
261  NS_LOG_FUNCTION (this);
262  return m_typeOfStation;
263 }
264 
265 Ptr<WifiMacQueue >
266 EdcaTxopN::GetQueue () const
267 {
268  NS_LOG_FUNCTION (this);
269  return m_queue;
270 }
271 
272 void
273 EdcaTxopN::SetMinCw (uint32_t minCw)
274 {
275  NS_LOG_FUNCTION (this << minCw);
276  m_dcf->SetCwMin (minCw);
277 }
278 
279 void
280 EdcaTxopN::SetMaxCw (uint32_t maxCw)
281 {
282  NS_LOG_FUNCTION (this << maxCw);
283  m_dcf->SetCwMax (maxCw);
284 }
285 
286 void
287 EdcaTxopN::SetAifsn (uint32_t aifsn)
288 {
289  NS_LOG_FUNCTION (this << aifsn);
290  m_dcf->SetAifsn (aifsn);
291 }
292 
293 uint32_t
294 EdcaTxopN::GetMinCw (void) const
295 {
296  NS_LOG_FUNCTION (this);
297  return m_dcf->GetCwMin ();
298 }
299 
300 uint32_t
301 EdcaTxopN::GetMaxCw (void) const
302 {
303  NS_LOG_FUNCTION (this);
304  return m_dcf->GetCwMax ();
305 }
306 
307 uint32_t
308 EdcaTxopN::GetAifsn (void) const
309 {
310  NS_LOG_FUNCTION (this);
311  return m_dcf->GetAifsn ();
312 }
313 
314 void
315 EdcaTxopN::SetTxMiddle (MacTxMiddle *txMiddle)
316 {
317  NS_LOG_FUNCTION (this << txMiddle);
318  m_txMiddle = txMiddle;
319 }
320 
321 Ptr<MacLow>
322 EdcaTxopN::Low (void)
323 {
324  NS_LOG_FUNCTION (this);
325  return m_low;
326 }
327 
328 void
329 EdcaTxopN::SetLow (Ptr<MacLow> low)
330 {
331  NS_LOG_FUNCTION (this << low);
332  m_low = low;
333 }
334 
335 bool
336 EdcaTxopN::NeedsAccess (void) const
337 {
338  NS_LOG_FUNCTION (this);
339  return !m_queue->IsEmpty () || m_currentPacket != 0 || m_baManager->HasPackets ();
340 }
341 
342 void
343 EdcaTxopN::NotifyAccessGranted (void)
344 {
345  NS_LOG_FUNCTION (this);
346  if (m_currentPacket == 0)
347  {
348  if (m_queue->IsEmpty () && !m_baManager->HasPackets ())
349  {
350  NS_LOG_DEBUG ("queue is empty");
351  return;
352  }
353  if (m_baManager->HasBar (m_currentBar))
354  {
355  SendBlockAckRequest (m_currentBar);
356  return;
357  }
358  /* check if packets need retransmission are stored in BlockAckManager */
359  m_currentPacket = m_baManager->GetNextPacket (m_currentHdr);
360  if (m_currentPacket == 0)
361  {
362  if (m_queue->PeekFirstAvailable (&m_currentHdr, m_currentPacketTimestamp, m_qosBlockedDestinations) == 0)
363  {
364  NS_LOG_DEBUG ("no available packets in the queue");
365  return;
366  }
367  if (m_currentHdr.IsQosData () && !m_currentHdr.GetAddr1 ().IsBroadcast ()
368  && m_blockAckThreshold > 0
369  && !m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
370  && SetupBlockAckIfNeeded ())
371  {
372  return;
373  }
374  m_currentPacket = m_queue->DequeueFirstAvailable (&m_currentHdr, m_currentPacketTimestamp, m_qosBlockedDestinations);
375  NS_ASSERT (m_currentPacket != 0);
376 
377  uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHdr);
378  m_currentHdr.SetSequenceNumber (sequence);
379  m_currentHdr.SetFragmentNumber (0);
380  m_currentHdr.SetNoMoreFragments ();
381  m_currentHdr.SetNoRetry ();
382  m_fragmentNumber = 0;
383  NS_LOG_DEBUG ("dequeued size=" << m_currentPacket->GetSize () <<
384  ", to=" << m_currentHdr.GetAddr1 () <<
385  ", seq=" << m_currentHdr.GetSequenceControl ());
386  if (m_currentHdr.IsQosData () && !m_currentHdr.GetAddr1 ().IsBroadcast ())
387  {
388  VerifyBlockAck ();
389  }
390  }
391  }
392  MacLowTransmissionParameters params;
393  params.DisableOverrideDurationId ();
394  if (m_currentHdr.GetAddr1 ().IsGroup ())
395  {
396  params.DisableRts ();
397  params.DisableAck ();
398  params.DisableNextData ();
399  m_low->StartTransmission (m_currentPacket,
400  &m_currentHdr,
401  params,
402  m_transmissionListener);
403 
404  NS_LOG_DEBUG ("tx broadcast");
405  }
406  else if (m_currentHdr.GetType () == WIFI_MAC_CTL_BACKREQ)
407  {
408  SendBlockAckRequest (m_currentBar);
409  }
410  else
411  {
412  if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck ())
413  {
414  params.DisableAck ();
415  }
416  else
417  {
418  params.EnableAck ();
419  }
420  if (NeedFragmentation () && ((m_currentHdr.IsQosData ()
421  && !m_currentHdr.IsQosAmsdu ())
422  ||
423  (m_currentHdr.IsData ()
424  && !m_currentHdr.IsQosData () && m_currentHdr.IsQosAmsdu ()))
425  && (m_blockAckThreshold == 0
426  || m_blockAckType == BASIC_BLOCK_ACK))
427  {
428  //With COMPRESSED_BLOCK_ACK fragmentation must be avoided.
429  params.DisableRts ();
430  WifiMacHeader hdr;
431  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
432  if (IsLastFragment ())
433  {
434  NS_LOG_DEBUG ("fragmenting last fragment size=" << fragment->GetSize ());
435  params.DisableNextData ();
436  }
437  else
438  {
439  NS_LOG_DEBUG ("fragmenting size=" << fragment->GetSize ());
440  params.EnableNextData (GetNextFragmentSize ());
441  }
442  m_low->StartTransmission (fragment, &hdr, params,
443  m_transmissionListener);
444  }
445  else
446  {
447  WifiMacHeader peekedHdr;
448  if (m_currentHdr.IsQosData ()
449  && m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (),
450  WifiMacHeader::ADDR1, m_currentHdr.GetAddr1 ())
451  && !m_currentHdr.GetAddr1 ().IsBroadcast ()
452  && m_aggregator != 0 && !m_currentHdr.IsRetry ())
453  {
454  /* here is performed aggregation */
455  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
456  m_aggregator->Aggregate (m_currentPacket, currentAggregatedPacket,
457  MapSrcAddressForAggregation (peekedHdr),
458  MapDestAddressForAggregation (peekedHdr));
459  bool aggregated = false;
460  bool isAmsdu = false;
461  Ptr<const Packet> peekedPacket = m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (),
462  WifiMacHeader::ADDR1,
463  m_currentHdr.GetAddr1 ());
464  while (peekedPacket != 0)
465  {
466  aggregated = m_aggregator->Aggregate (peekedPacket, currentAggregatedPacket,
467  MapSrcAddressForAggregation (peekedHdr),
468  MapDestAddressForAggregation (peekedHdr));
469  if (aggregated)
470  {
471  isAmsdu = true;
472  m_queue->Remove (peekedPacket);
473  }
474  else
475  {
476  break;
477  }
478  peekedPacket = m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (),
479  WifiMacHeader::ADDR1, m_currentHdr.GetAddr1 ());
480  }
481  if (isAmsdu)
482  {
483  m_currentHdr.SetQosAmsdu ();
484  m_currentHdr.SetAddr3 (m_low->GetBssid ());
485  m_currentPacket = currentAggregatedPacket;
486  currentAggregatedPacket = 0;
487  NS_LOG_DEBUG ("tx unicast A-MSDU");
488  }
489  }
490  if (NeedRts ())
491  {
492  params.EnableRts ();
493  NS_LOG_DEBUG ("tx unicast rts");
494  }
495  else
496  {
497  params.DisableRts ();
498  NS_LOG_DEBUG ("tx unicast");
499  }
500  params.DisableNextData ();
501  m_low->StartTransmission (m_currentPacket, &m_currentHdr,
502  params, m_transmissionListener);
503  CompleteTx ();
504  }
505  }
506 }
507 
508 void EdcaTxopN::NotifyInternalCollision (void)
509 {
510  NS_LOG_FUNCTION (this);
511  NotifyCollision ();
512 }
513 
514 void
515 EdcaTxopN::NotifyCollision (void)
516 {
517  NS_LOG_FUNCTION (this);
518  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
519  RestartAccessIfNeeded ();
520 }
521 
522 void
523 EdcaTxopN::GotCts (double snr, WifiMode txMode)
524 {
525  NS_LOG_FUNCTION (this << snr << txMode);
526  NS_LOG_DEBUG ("got cts");
527 }
528 
529 void
530 EdcaTxopN::MissedCts (void)
531 {
532  NS_LOG_FUNCTION (this);
533  NS_LOG_DEBUG ("missed cts");
534  if (!NeedRtsRetransmission ())
535  {
536  NS_LOG_DEBUG ("Cts Fail");
537  m_stationManager->ReportFinalRtsFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
538  if (!m_txFailedCallback.IsNull ())
539  {
540  m_txFailedCallback (m_currentHdr);
541  }
542  // to reset the dcf.
543  m_currentPacket = 0;
544  m_dcf->ResetCw ();
545  }
546  else
547  {
548  m_dcf->UpdateFailedCw ();
549  }
550  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
551  RestartAccessIfNeeded ();
552 }
553 
554 void
556 {
557  NS_LOG_FUNCTION (this);
558  m_queue->Flush ();
559  m_currentPacket = 0;
560 }
561 
562 void
563 EdcaTxopN::NotifyChannelSensing (void)
564 {
565  NS_LOG_FUNCTION (this);
566  m_queue->Flush ();
567  m_currentPacket = 0;
568 }
569 
570 void
571 EdcaTxopN::Queue (Ptr<const Packet> packet, const WifiMacHeader &hdr)
572 {
573  NS_LOG_FUNCTION (this << packet << &hdr);
574  WifiMacTrailer fcs;
575  uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.GetSerializedSize ();
576  m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr,
577  packet, fullPacketSize);
578  m_queue->Enqueue (packet, hdr);
579  StartAccessIfNeeded ();
580 }
581 
582 void
583 EdcaTxopN::GotAck (double snr, WifiMode txMode)
584 {
585  NS_LOG_FUNCTION (this << snr << txMode);
586  if (!NeedFragmentation ()
587  || IsLastFragment ()
588  || m_currentHdr.IsQosAmsdu ())
589  {
590  NS_LOG_DEBUG ("got ack. tx done.");
591  if (!m_txOkCallback.IsNull ())
592  {
593  m_txOkCallback (m_currentHdr);
594  }
595 
596  if (m_currentHdr.IsAction ())
597  {
598  WifiActionHeader actionHdr;
599  Ptr<Packet> p = m_currentPacket->Copy ();
600  p->RemoveHeader (actionHdr);
601  if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK
602  && actionHdr.GetAction ().blockAck == WifiActionHeader::BLOCK_ACK_DELBA)
603  {
604  MgtDelBaHeader delBa;
605  p->PeekHeader (delBa);
606  if (delBa.IsByOriginator ())
607  {
608  m_baManager->TearDownBlockAck (m_currentHdr.GetAddr1 (), delBa.GetTid ());
609  }
610  else
611  {
612  m_low->DestroyBlockAckAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
613  }
614  }
615  }
616  m_currentPacket = 0;
617 
618  m_dcf->ResetCw ();
619  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
620  RestartAccessIfNeeded ();
621  }
622  else
623  {
624  NS_LOG_DEBUG ("got ack. tx not done, size=" << m_currentPacket->GetSize ());
625  }
626 }
627 
628 void
629 EdcaTxopN::MissedAck (void)
630 {
631  NS_LOG_FUNCTION (this);
632  NS_LOG_DEBUG ("missed ack");
633  if (!NeedDataRetransmission ())
634  {
635  NS_LOG_DEBUG ("Ack Fail");
636  m_stationManager->ReportFinalDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
637  if (!m_txFailedCallback.IsNull ())
638  {
639  m_txFailedCallback (m_currentHdr);
640  }
641  // to reset the dcf.
642  m_currentPacket = 0;
643  m_dcf->ResetCw ();
644  }
645  else
646  {
647  NS_LOG_DEBUG ("Retransmit");
648  m_currentHdr.SetRetry ();
649  m_dcf->UpdateFailedCw ();
650  }
651  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
652  RestartAccessIfNeeded ();
653 }
654 
655 void
656 EdcaTxopN::MissedBlockAck (void)
657 {
658  NS_LOG_FUNCTION (this);
659  NS_LOG_DEBUG ("missed block ack");
660  //should i report this to station addressed by ADDR1?
661  NS_LOG_DEBUG ("Retransmit block ack request");
662  m_currentHdr.SetRetry ();
663  m_dcf->UpdateFailedCw ();
664 
665  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
666  RestartAccessIfNeeded ();
667 }
668 
669 Ptr<MsduAggregator>
670 EdcaTxopN::GetMsduAggregator (void) const
671 {
672  return m_aggregator;
673 }
674 
675 void
676 EdcaTxopN::RestartAccessIfNeeded (void)
677 {
678  NS_LOG_FUNCTION (this);
679  if ((m_currentPacket != 0
680  || !m_queue->IsEmpty () || m_baManager->HasPackets ())
681  && !m_dcf->IsAccessRequested ())
682  {
683  m_manager->RequestAccess (m_dcf);
684  }
685 }
686 
687 void
688 EdcaTxopN::StartAccessIfNeeded (void)
689 {
690  NS_LOG_FUNCTION (this);
691  if (m_currentPacket == 0
692  && (!m_queue->IsEmpty () || m_baManager->HasPackets ())
693  && !m_dcf->IsAccessRequested ())
694  {
695  m_manager->RequestAccess (m_dcf);
696  }
697 }
698 
699 bool
700 EdcaTxopN::NeedRts (void)
701 {
702  NS_LOG_FUNCTION (this);
703  return m_stationManager->NeedRts (m_currentHdr.GetAddr1 (), &m_currentHdr,
704  m_currentPacket);
705 }
706 
707 bool
708 EdcaTxopN::NeedRtsRetransmission (void)
709 {
710  NS_LOG_FUNCTION (this);
711  return m_stationManager->NeedRtsRetransmission (m_currentHdr.GetAddr1 (), &m_currentHdr,
712  m_currentPacket);
713 }
714 
715 bool
716 EdcaTxopN::NeedDataRetransmission (void)
717 {
718  NS_LOG_FUNCTION (this);
719  return m_stationManager->NeedDataRetransmission (m_currentHdr.GetAddr1 (), &m_currentHdr,
720  m_currentPacket);
721 }
722 
723 void
724 EdcaTxopN::NextFragment (void)
725 {
726  NS_LOG_FUNCTION (this);
727  m_fragmentNumber++;
728 }
729 
730 void
731 EdcaTxopN::StartNext (void)
732 {
733  NS_LOG_FUNCTION (this);
734  NS_LOG_DEBUG ("start next packet fragment");
735  /* this callback is used only for fragments. */
736  NextFragment ();
737  WifiMacHeader hdr;
738  Ptr<Packet> fragment = GetFragmentPacket (&hdr);
739  MacLowTransmissionParameters params;
740  params.EnableAck ();
741  params.DisableRts ();
742  params.DisableOverrideDurationId ();
743  if (IsLastFragment ())
744  {
745  params.DisableNextData ();
746  }
747  else
748  {
749  params.EnableNextData (GetNextFragmentSize ());
750  }
751  Low ()->StartTransmission (fragment, &hdr, params, m_transmissionListener);
752 }
753 
754 void
755 EdcaTxopN::Cancel (void)
756 {
757  NS_LOG_FUNCTION (this);
758  NS_LOG_DEBUG ("transmission cancelled");
759 }
760 
761 void
762 EdcaTxopN::EndTxNoAck (void)
763 {
764  NS_LOG_FUNCTION (this);
765  NS_LOG_DEBUG ("a transmission that did not require an ACK just finished");
766  m_currentPacket = 0;
767  m_dcf->ResetCw ();
768  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
769  StartAccessIfNeeded ();
770 }
771 
772 bool
773 EdcaTxopN::NeedFragmentation (void) const
774 {
775  NS_LOG_FUNCTION (this);
776  return m_stationManager->NeedFragmentation (m_currentHdr.GetAddr1 (), &m_currentHdr,
777  m_currentPacket);
778 }
779 
780 uint32_t
781 EdcaTxopN::GetFragmentSize (void)
782 {
783  NS_LOG_FUNCTION (this);
784  return m_stationManager->GetFragmentSize (m_currentHdr.GetAddr1 (), &m_currentHdr,
785  m_currentPacket, m_fragmentNumber);
786 }
787 
788 uint32_t
789 EdcaTxopN::GetNextFragmentSize (void)
790 {
791  NS_LOG_FUNCTION (this);
792  return m_stationManager->GetFragmentSize (m_currentHdr.GetAddr1 (), &m_currentHdr,
793  m_currentPacket, m_fragmentNumber + 1);
794 }
795 
796 uint32_t
797 EdcaTxopN::GetFragmentOffset (void)
798 {
799  NS_LOG_FUNCTION (this);
800  return m_stationManager->GetFragmentOffset (m_currentHdr.GetAddr1 (), &m_currentHdr,
801  m_currentPacket, m_fragmentNumber);
802 }
803 
804 
805 bool
806 EdcaTxopN::IsLastFragment (void) const
807 {
808  NS_LOG_FUNCTION (this);
809  return m_stationManager->IsLastFragment (m_currentHdr.GetAddr1 (), &m_currentHdr,
810  m_currentPacket, m_fragmentNumber);
811 }
812 
813 Ptr<Packet>
814 EdcaTxopN::GetFragmentPacket (WifiMacHeader *hdr)
815 {
816  NS_LOG_FUNCTION (this << hdr);
817  *hdr = m_currentHdr;
818  hdr->SetFragmentNumber (m_fragmentNumber);
819  uint32_t startOffset = GetFragmentOffset ();
820  Ptr<Packet> fragment;
821  if (IsLastFragment ())
822  {
823  hdr->SetNoMoreFragments ();
824  }
825  else
826  {
827  hdr->SetMoreFragments ();
828  }
829  fragment = m_currentPacket->CreateFragment (startOffset,
830  GetFragmentSize ());
831  return fragment;
832 }
833 
834 void
835 EdcaTxopN::SetAccessCategory (enum AcIndex ac)
836 {
837  NS_LOG_FUNCTION (this << static_cast<uint32_t> (ac));
838  m_ac = ac;
839 }
840 
841 Mac48Address
843 {
844  NS_LOG_FUNCTION (this << &hdr);
845  Mac48Address retval;
846  if (m_typeOfStation == STA || m_typeOfStation == ADHOC_STA)
847  {
848  retval = hdr.GetAddr2 ();
849  }
850  else
851  {
852  retval = hdr.GetAddr3 ();
853  }
854  return retval;
855 }
856 
858 EdcaTxopN::MapDestAddressForAggregation (const WifiMacHeader &hdr)
859 {
860  NS_LOG_FUNCTION (this << &hdr);
861  Mac48Address retval;
862  if (m_typeOfStation == AP || m_typeOfStation == ADHOC_STA)
863  {
864  retval = hdr.GetAddr1 ();
865  }
866  else
867  {
868  retval = hdr.GetAddr3 ();
869  }
870  return retval;
871 }
872 
873 void
874 EdcaTxopN::SetMsduAggregator (Ptr<MsduAggregator> aggr)
875 {
876  NS_LOG_FUNCTION (this << aggr);
877  m_aggregator = aggr;
878 }
879 
880 void
881 EdcaTxopN::PushFront (Ptr<const Packet> packet, const WifiMacHeader &hdr)
882 {
883  NS_LOG_FUNCTION (this << packet << &hdr);
884  WifiMacTrailer fcs;
885  uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.GetSerializedSize ();
886  m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr,
887  packet, fullPacketSize);
888  m_queue->PushFront (packet, hdr);
889  StartAccessIfNeeded ();
890 }
891 
892 void
893 EdcaTxopN::GotAddBaResponse (const MgtAddBaResponseHeader *respHdr, Mac48Address recipient)
894 {
895  NS_LOG_FUNCTION (this << respHdr << recipient);
896  NS_LOG_DEBUG ("received ADDBA response from " << recipient);
897  uint8_t tid = respHdr->GetTid ();
898  if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::PENDING))
899  {
900  if (respHdr->GetStatusCode ().IsSuccess ())
901  {
902  NS_LOG_DEBUG ("block ack agreement established with " << recipient);
903  m_baManager->UpdateAgreement (respHdr, recipient);
904  }
905  else
906  {
907  NS_LOG_DEBUG ("discard ADDBA response" << recipient);
908  m_baManager->NotifyAgreementUnsuccessful (recipient, tid);
909  }
910  }
911  RestartAccessIfNeeded ();
912 }
913 
914 void
915 EdcaTxopN::GotDelBaFrame (const MgtDelBaHeader *delBaHdr, Mac48Address recipient)
916 {
917  NS_LOG_FUNCTION (this << delBaHdr << recipient);
918  NS_LOG_DEBUG ("received DELBA frame from=" << recipient);
919  m_baManager->TearDownBlockAck (recipient, delBaHdr->GetTid ());
920 }
921 
922 void
923 EdcaTxopN::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address recipient)
924 {
925  NS_LOG_FUNCTION (this << blockAck << recipient);
926  NS_LOG_DEBUG ("got block ack from=" << recipient);
927  m_baManager->NotifyGotBlockAck (blockAck, recipient);
928  m_currentPacket = 0;
929  m_dcf->ResetCw ();
930  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
931  RestartAccessIfNeeded ();
932 }
933 
934 void
935 EdcaTxopN::VerifyBlockAck (void)
936 {
937  NS_LOG_FUNCTION (this);
938  uint8_t tid = m_currentHdr.GetQosTid ();
939  Mac48Address recipient = m_currentHdr.GetAddr1 ();
940  uint16_t sequence = m_currentHdr.GetSequenceNumber ();
941  if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::INACTIVE))
942  {
943  m_baManager->SwitchToBlockAckIfNeeded (recipient, tid, sequence);
944  }
945  if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED))
946  {
947  m_currentHdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK);
948  }
949 }
950 
951 void
952 EdcaTxopN::CompleteTx (void)
953 {
954  NS_LOG_FUNCTION (this);
955  if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck ())
956  {
957  if (!m_currentHdr.IsRetry ())
958  {
959  m_baManager->StorePacket (m_currentPacket, m_currentHdr, m_currentPacketTimestamp);
960  }
961  m_baManager->NotifyMpduTransmission (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid (),
962  m_txMiddle->GetNextSeqNumberByTidAndAddress (m_currentHdr.GetQosTid (),
963  m_currentHdr.GetAddr1 ()));
964  }
965 }
966 
967 bool
968 EdcaTxopN::SetupBlockAckIfNeeded ()
969 {
970  NS_LOG_FUNCTION (this);
971  uint8_t tid = m_currentHdr.GetQosTid ();
972  Mac48Address recipient = m_currentHdr.GetAddr1 ();
973 
974  uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, WifiMacHeader::ADDR1, recipient);
975 
976  if (packets >= m_blockAckThreshold)
977  {
978  /* Block ack setup */
979  uint16_t startingSequence = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
980  SendAddBaRequest (recipient, tid, startingSequence, m_blockAckInactivityTimeout, true);
981  return true;
982  }
983  return false;
984 }
985 
986 void
987 EdcaTxopN::SendBlockAckRequest (const struct Bar &bar)
988 {
989  NS_LOG_FUNCTION (this << &bar);
990  WifiMacHeader hdr;
991  hdr.SetType (WIFI_MAC_CTL_BACKREQ);
992  hdr.SetAddr1 (bar.recipient);
993  hdr.SetAddr2 (m_low->GetAddress ());
994  hdr.SetAddr3 (m_low->GetBssid ());
995  hdr.SetDsNotTo ();
996  hdr.SetDsNotFrom ();
997  hdr.SetNoRetry ();
998  hdr.SetNoMoreFragments ();
999 
1000  m_currentPacket = bar.bar;
1001  m_currentHdr = hdr;
1002 
1003  MacLowTransmissionParameters params;
1004  params.DisableRts ();
1005  params.DisableNextData ();
1006  params.DisableOverrideDurationId ();
1007  if (bar.immediate)
1008  {
1009  if (m_blockAckType == BASIC_BLOCK_ACK)
1010  {
1011  params.EnableBasicBlockAck ();
1012  }
1013  else if (m_blockAckType == COMPRESSED_BLOCK_ACK)
1014  {
1015  params.EnableCompressedBlockAck ();
1016  }
1017  else if (m_blockAckType == MULTI_TID_BLOCK_ACK)
1018  {
1019  NS_FATAL_ERROR ("Multi-tid block ack is not supported");
1020  }
1021  }
1022  else
1023  {
1024  //Delayed block ack
1025  params.EnableAck ();
1026  }
1027  m_low->StartTransmission (m_currentPacket, &m_currentHdr, params, m_transmissionListener);
1028 }
1029 
1030 void
1031 EdcaTxopN::CompleteConfig (void)
1032 {
1033  NS_LOG_FUNCTION (this);
1034  m_baManager->SetTxMiddle (m_txMiddle);
1035  m_low->RegisterBlockAckListenerForAc (m_ac, m_blockAckListener);
1036  m_baManager->SetBlockAckInactivityCallback (MakeCallback (&EdcaTxopN::SendDelbaFrame, this));
1037 }
1038 
1039 void
1040 EdcaTxopN::SetBlockAckThreshold (uint8_t threshold)
1041 {
1042  NS_LOG_FUNCTION (this << static_cast<uint32_t> (threshold));
1043  m_blockAckThreshold = threshold;
1044  m_baManager->SetBlockAckThreshold (threshold);
1045 }
1046 
1047 void
1048 EdcaTxopN::SetBlockAckInactivityTimeout (uint16_t timeout)
1049 {
1050  NS_LOG_FUNCTION (this << timeout);
1051  m_blockAckInactivityTimeout = timeout;
1052 }
1053 
1054 uint8_t
1055 EdcaTxopN::GetBlockAckThreshold (void) const
1056 {
1057  NS_LOG_FUNCTION (this);
1058  return m_blockAckThreshold;
1059 }
1060 
1061 void
1062 EdcaTxopN::SendAddBaRequest (Mac48Address dest, uint8_t tid, uint16_t startSeq,
1063  uint16_t timeout, bool immediateBAck)
1064 {
1065  NS_LOG_FUNCTION (this << dest << static_cast<uint32_t> (tid) << startSeq << timeout << immediateBAck);
1066  NS_LOG_DEBUG ("sent ADDBA request to " << dest);
1067  WifiMacHeader hdr;
1068  hdr.SetAction ();
1069  hdr.SetAddr1 (dest);
1070  hdr.SetAddr2 (m_low->GetAddress ());
1071  hdr.SetAddr3 (m_low->GetAddress ());
1072  hdr.SetDsNotTo ();
1073  hdr.SetDsNotFrom ();
1074 
1075  WifiActionHeader actionHdr;
1076  WifiActionHeader::ActionValue action;
1077  action.blockAck = WifiActionHeader::BLOCK_ACK_ADDBA_REQUEST;
1078  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1079 
1080  Ptr<Packet> packet = Create<Packet> ();
1081  /*Setting ADDBARequest header*/
1082  MgtAddBaRequestHeader reqHdr;
1083  reqHdr.SetAmsduSupport (true);
1084  if (immediateBAck)
1085  {
1086  reqHdr.SetImmediateBlockAck ();
1087  }
1088  else
1089  {
1090  reqHdr.SetDelayedBlockAck ();
1091  }
1092  reqHdr.SetTid (tid);
1093  /* For now we don't use buffer size field in the ADDBA request frame. The recipient
1094  * will choose how many packets it can receive under block ack.
1095  */
1096  reqHdr.SetBufferSize (0);
1097  reqHdr.SetTimeout (timeout);
1098  reqHdr.SetStartingSequence (startSeq);
1099 
1100  m_baManager->CreateAgreement (&reqHdr, dest);
1101 
1102  packet->AddHeader (reqHdr);
1103  packet->AddHeader (actionHdr);
1104 
1105  m_currentPacket = packet;
1106  m_currentHdr = hdr;
1107 
1108  uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHdr);
1109  m_currentHdr.SetSequenceNumber (sequence);
1110  m_currentHdr.SetFragmentNumber (0);
1111  m_currentHdr.SetNoMoreFragments ();
1112  m_currentHdr.SetNoRetry ();
1113 
1114  MacLowTransmissionParameters params;
1115  params.EnableAck ();
1116  params.DisableRts ();
1117  params.DisableNextData ();
1118  params.DisableOverrideDurationId ();
1119 
1120  m_low->StartTransmission (m_currentPacket, &m_currentHdr, params,
1121  m_transmissionListener);
1122 }
1123 
1124 void
1125 EdcaTxopN::SendDelbaFrame (Mac48Address addr, uint8_t tid, bool byOriginator)
1126 {
1127  NS_LOG_FUNCTION (this << addr << static_cast<uint32_t> (tid) << byOriginator);
1128  WifiMacHeader hdr;
1129  hdr.SetAction ();
1130  hdr.SetAddr1 (addr);
1131  hdr.SetAddr2 (m_low->GetAddress ());
1132  hdr.SetAddr3 (m_low->GetAddress ());
1133  hdr.SetDsNotTo ();
1134  hdr.SetDsNotFrom ();
1135 
1136  MgtDelBaHeader delbaHdr;
1137  delbaHdr.SetTid (tid);
1138  if (byOriginator)
1139  {
1140  delbaHdr.SetByOriginator ();
1141  }
1142  else
1143  {
1144  delbaHdr.SetByRecipient ();
1145  }
1146 
1147  WifiActionHeader actionHdr;
1148  WifiActionHeader::ActionValue action;
1149  action.blockAck = WifiActionHeader::BLOCK_ACK_DELBA;
1150  actionHdr.SetAction (WifiActionHeader::BLOCK_ACK, action);
1151 
1152  Ptr<Packet> packet = Create<Packet> ();
1153  packet->AddHeader (delbaHdr);
1154  packet->AddHeader (actionHdr);
1155 
1156  PushFront (packet, hdr);
1157 }
1158 
1159 int64_t
1161 {
1162  NS_LOG_FUNCTION (this << stream);
1163  m_rng->AssignStreams (stream);
1164  return 1;
1165 }
1166 
1167 void
1169 {
1170  NS_LOG_FUNCTION (this);
1171  m_dcf->ResetCw ();
1172  m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ()));
1174 }
1175 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
keep track of time unit.
Definition: nstime.h:149
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
virtual void DoNotifyChannelSwitching(Time duration, uint16_t toChannel)
Definition: edca-txop-n.cc:65
TypeId AddConstructor(void)
Definition: type-id.h:388
void NotifyGotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address recipient)
void CreateAgreement(const MgtAddBaRequestHeader *reqHdr, Mac48Address recipient)
void StorePacket(Ptr< const Packet > packet, const WifiMacHeader &hdr, Time tStamp)
void RequestAccess(DcfState *state)
Definition: dcf-manager.cc:419
#define NS_ASSERT(condition)
Definition: assert.h:64
void NotifyChannelSwitching(Time duration)
Definition: edca-txop-n.cc:555
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
bool IsBroadcast(void) const
void SetAifsn(uint32_t aifsn)
Definition: dcf-manager.cc:57
bool HasPackets(void) const
void ResetCw(void)
Definition: dcf-manager.cc:90
virtual void BlockAckInactivityTimeout(Mac48Address address, uint8_t tid)
Definition: edca-txop-n.cc:136
listen to events coming from ns3::MacLow.
Definition: mac-low.h:55
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:88
void Add(DcfState *dcf)
Definition: dcf-manager.cc:338
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
virtual void DoNotifyCollision(void)
Definition: edca-txop-n.cc:61
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Definition: packet.cc:243
void UpdateAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address recipient)
virtual void GotAck(double snr, WifiMode txMode)
Definition: edca-txop-n.cc:94
Hold an unsigned integer type.
Definition: uinteger.h:46
void NotifyAgreementUnsuccessful(Mac48Address recipient, uint8_t tid)
Manage a set of ns3::DcfStateHandle a set of independent ns3::DcfState, each of which represents a si...
Definition: dcf-manager.h:175
keep track of the state needed for a single DCF function.Multiple instances of a DcfState can be regi...
Definition: dcf-manager.h:46
Headers for Block ack response.
Definition: ctrl-headers.h:102
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
bool IsAccessRequested(void) const
Definition: dcf-manager.cc:133
int64_t AssignStreams(int64_t stream)
virtual void GotCts(double snr, WifiMode txMode)
Definition: edca-txop-n.cc:86
Ptr< Packet > Copy(void) const
Definition: packet.cc:131
void StartBackoffNow(uint32_t nSlots)
Definition: dcf-manager.cc:109
hold objects of type Ptr<T>
Definition: pointer.h:33
listen for block ack events.
Definition: mac-low.h:169
bool IsGroup(void) const
bool ExistsAgreementInState(Mac48Address recipient, uint8_t tid, enum OriginatorBlockAckAgreement::State state) const
an EUI-48 address
Definition: mac48-address.h:41
Ptr< const Packet > GetNextPacket(WifiMacHeader &hdr)
bool SwitchToBlockAckIfNeeded(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
virtual void DoNotifyAccessGranted(void)
Definition: edca-txop-n.cc:53
uint32_t GetCw(void) const
Definition: dcf-manager.cc:118
void SetBlockAckThreshold(uint8_t nPackets)
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
void UpdateFailedCw(void)
Definition: dcf-manager.cc:95
bool ExistsAgreement(Mac48Address recipient, uint8_t tid) const
virtual void DoNotifyInternalCollision(void)
Definition: edca-txop-n.cc:57
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
AcIndex
Definition: qos-utils.h:35
void NotifyMpduTransmission(Mac48Address recipient, uint8_t tid, uint16_t nextSeqNumber)
virtual void DoInitialize(void)
Definition: object.cc:342
void TearDownBlockAck(Mac48Address recipient, uint8_t tid)
Mac48Address MapSrcAddressForAggregation(const WifiMacHeader &hdr)
Definition: edca-txop-n.cc:842
virtual void GotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address source)
Definition: edca-txop-n.cc:102