A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
block-ack-manager.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009, 2010 MIRKO BANCHI
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mirko Banchi <mk.banchi@gmail.com>
19  */
20 #include "ns3/log.h"
21 #include "ns3/assert.h"
22 #include "ns3/simulator.h"
23 #include "ns3/fatal-error.h"
24 
25 #include "block-ack-manager.h"
26 #include "mgt-headers.h"
27 #include "ctrl-headers.h"
28 #include "wifi-mac-header.h"
29 #include "edca-txop-n.h"
30 #include "mac-low.h"
31 #include "wifi-mac-queue.h"
32 #include "mac-tx-middle.h"
33 
34 NS_LOG_COMPONENT_DEFINE ("BlockAckManager");
35 
36 namespace ns3 {
37 
38 BlockAckManager::Item::Item ()
39 {
40  NS_LOG_FUNCTION (this);
41 }
42 
43 BlockAckManager::Item::Item (Ptr<const Packet> packet, const WifiMacHeader &hdr, Time tStamp)
44  : packet (packet),
45  hdr (hdr),
46  timestamp (tStamp)
47 {
48  NS_LOG_FUNCTION (this << packet << hdr << tStamp);
49 }
50 
51 Bar::Bar ()
52 {
53  NS_LOG_FUNCTION (this);
54 }
55 
56 Bar::Bar (Ptr<const Packet> bar, Mac48Address recipient, uint8_t tid, bool immediate)
57  : bar (bar),
58  recipient (recipient),
59  tid (tid),
60  immediate (immediate)
61 {
62  NS_LOG_FUNCTION (this << bar << recipient << static_cast<uint32_t> (tid) << immediate);
63 }
64 
65 BlockAckManager::BlockAckManager ()
66 {
67  NS_LOG_FUNCTION (this);
68 }
69 
70 BlockAckManager::~BlockAckManager ()
71 {
72  NS_LOG_FUNCTION (this);
73  m_queue = 0;
74  m_agreements.clear ();
75  m_retryPackets.clear ();
76 }
77 
78 bool
79 BlockAckManager::ExistsAgreement (Mac48Address recipient, uint8_t tid) const
80 {
81  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid));
82  return (m_agreements.find (std::make_pair (recipient, tid)) != m_agreements.end ());
83 }
84 
85 bool
87  enum OriginatorBlockAckAgreement::State state) const
88 {
89  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid) << state);
90  AgreementsCI it;
91  it = m_agreements.find (std::make_pair (recipient, tid));
92  if (it != m_agreements.end ())
93  {
94  switch (state)
95  {
96  case OriginatorBlockAckAgreement::INACTIVE:
97  return it->second.first.IsInactive ();
98  case OriginatorBlockAckAgreement::ESTABLISHED:
99  return it->second.first.IsEstablished ();
100  case OriginatorBlockAckAgreement::PENDING:
101  return it->second.first.IsPending ();
102  case OriginatorBlockAckAgreement::UNSUCCESSFUL:
103  return it->second.first.IsUnsuccessful ();
104  default:
105  NS_FATAL_ERROR ("Invalid state for block ack agreement");
106  }
107  }
108  return false;
109 }
110 
111 void
113 {
114  NS_LOG_FUNCTION (this << reqHdr << recipient);
115  std::pair<Mac48Address, uint8_t> key (recipient, reqHdr->GetTid ());
116  OriginatorBlockAckAgreement agreement (recipient, reqHdr->GetTid ());
117  agreement.SetStartingSequence (reqHdr->GetStartingSequence ());
118  /* for now we assume that originator doesn't use this field. Use of this field
119  is mandatory only for recipient */
120  agreement.SetBufferSize (0);
121  agreement.SetTimeout (reqHdr->GetTimeout ());
122  agreement.SetAmsduSupport (reqHdr->IsAmsduSupported ());
123  if (reqHdr->IsImmediateBlockAck ())
124  {
125  agreement.SetImmediateBlockAck ();
126  }
127  else
128  {
129  agreement.SetDelayedBlockAck ();
130  }
131  agreement.SetState (OriginatorBlockAckAgreement::PENDING);
132  PacketQueue queue (0);
133  std::pair<OriginatorBlockAckAgreement, PacketQueue> value (agreement, queue);
134  m_agreements.insert (std::make_pair (key, value));
135  m_blockPackets (recipient, reqHdr->GetTid ());
136 }
137 
138 void
140 {
141  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid));
142  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
143  if (it != m_agreements.end ())
144  {
145  for (std::list<PacketQueueI>::iterator i = m_retryPackets.begin (); i != m_retryPackets.end ();)
146  {
147  if ((*i)->hdr.GetAddr1 () == recipient && (*i)->hdr.GetQosTid () == tid)
148  {
149  i = m_retryPackets.erase (i);
150  }
151  else
152  {
153  i++;
154  }
155  }
156  m_agreements.erase (it);
157  //remove scheduled bar
158  for (std::list<Bar>::iterator i = m_bars.begin (); i != m_bars.end ();)
159  {
160  if (i->recipient == recipient && i->tid == tid)
161  {
162  i = m_bars.erase (i);
163  }
164  else
165  {
166  i++;
167  }
168  }
169  }
170 }
171 
172 void
174 {
175  NS_LOG_FUNCTION (this << respHdr << recipient);
176  uint8_t tid = respHdr->GetTid ();
177  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
178  if (it != m_agreements.end ())
179  {
180  OriginatorBlockAckAgreement& agreement = it->second.first;
181  agreement.SetBufferSize (respHdr->GetBufferSize () + 1);
182  agreement.SetTimeout (respHdr->GetTimeout ());
183  agreement.SetAmsduSupport (respHdr->IsAmsduSupported ());
184  if (respHdr->IsImmediateBlockAck ())
185  {
186  agreement.SetImmediateBlockAck ();
187  }
188  else
189  {
190  agreement.SetDelayedBlockAck ();
191  }
192  agreement.SetState (OriginatorBlockAckAgreement::ESTABLISHED);
193  if (agreement.GetTimeout () != 0)
194  {
195  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
196  agreement.m_inactivityEvent = Simulator::Schedule (timeout,
197  &BlockAckManager::InactivityTimeout,
198  this,
199  recipient, tid);
200  }
201  }
202  m_unblockPackets (recipient, tid);
203 }
204 
205 void
207 {
208  NS_LOG_FUNCTION (this << packet << hdr << tStamp);
209  NS_ASSERT (hdr.IsQosData ());
210 
211  uint8_t tid = hdr.GetQosTid ();
212  Mac48Address recipient = hdr.GetAddr1 ();
213 
214  Item item (packet, hdr, tStamp);
215  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
216  NS_ASSERT (it != m_agreements.end ());
217  it->second.second.push_back (item);
218 }
219 
222 {
223  NS_LOG_FUNCTION (this << &hdr);
224  Ptr<const Packet> packet = 0;
225  if (m_retryPackets.size () > 0)
226  {
227  CleanupBuffers ();
228  PacketQueueI queueIt = m_retryPackets.front ();
229  m_retryPackets.pop_front ();
230  packet = queueIt->packet;
231  hdr = queueIt->hdr;
232  hdr.SetRetry ();
233  NS_LOG_INFO ("Retry packet seq=" << hdr.GetSequenceNumber ());
234  uint8_t tid = hdr.GetQosTid ();
235  Mac48Address recipient = hdr.GetAddr1 ();
236 
237  if (ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED)
238  || SwitchToBlockAckIfNeeded (recipient, tid, hdr.GetSequenceNumber ()))
239  {
240  hdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK);
241  }
242  else
243  {
244  /* From section 9.10.3 in IEEE802.11e standard:
245  * In order to improve efficiency, originators using the Block Ack facility
246  * may send MPDU frames with the Ack Policy subfield in QoS control frames
247  * set to Normal Ack if only a few MPDUs are available for transmission.[...]
248  * When there are sufficient number of MPDUs, the originator may switch back to
249  * the use of Block Ack.
250  */
251  hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
252  AgreementsI i = m_agreements.find (std::make_pair (recipient, tid));
253  i->second.second.erase (queueIt);
254  }
255  }
256  return packet;
257 }
258 
259 bool
260 BlockAckManager::HasBar (struct Bar &bar)
261 {
262  NS_LOG_FUNCTION (this << &bar);
263  if (m_bars.size () > 0)
264  {
265  bar = m_bars.front ();
266  m_bars.pop_front ();
267  return true;
268  }
269  return false;
270 }
271 
272 bool
274 {
275  NS_LOG_FUNCTION (this);
276  return (m_retryPackets.size () > 0 || m_bars.size () > 0);
277 }
278 
279 uint32_t
281 {
282  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid));
283  uint32_t nPackets = 0;
284  if (ExistsAgreement (recipient, tid))
285  {
286  AgreementsCI it = m_agreements.find (std::make_pair (recipient, tid));
287  PacketQueueCI queueIt = (*it).second.second.begin ();
288  uint16_t currentSeq = 0;
289  while (queueIt != (*it).second.second.end ())
290  {
291  currentSeq = (*queueIt).hdr.GetSequenceNumber ();
292  nPackets++;
293  /* a fragmented packet must be counted as one packet */
294  while (queueIt != (*it).second.second.end () && (*queueIt).hdr.GetSequenceNumber () == currentSeq)
295  {
296  queueIt++;
297  }
298  }
299  return nPackets;
300  }
301  return 0;
302 }
303 
304 uint32_t
306 {
307  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid));
308  uint32_t nPackets = 0;
309  uint16_t currentSeq = 0;
310  if (ExistsAgreement (recipient, tid))
311  {
312  std::list<PacketQueueI>::const_iterator it = m_retryPackets.begin ();
313  while (it != m_retryPackets.end ())
314  {
315  if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
316  {
317  currentSeq = (*it)->hdr.GetSequenceNumber ();
318  nPackets++;
319  /* a fragmented packet must be counted as one packet */
320  while (it != m_retryPackets.end () && (*it)->hdr.GetSequenceNumber () == currentSeq)
321  {
322  it++;
323  }
324  }
325  }
326  }
327  return nPackets;
328 }
329 
330 void
332 {
333  NS_LOG_FUNCTION (this << static_cast<uint32_t> (nPackets));
334  m_blockAckThreshold = nPackets;
335 }
336 
337 void
339 {
340  NS_LOG_FUNCTION (this << blockAck << recipient);
341  uint16_t sequenceFirstLost = 0;
342  if (!blockAck->IsMultiTid ())
343  {
344  uint8_t tid = blockAck->GetTidInfo ();
345  if (ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED))
346  {
347  bool foundFirstLost = false;
348  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
349  PacketQueueI queueEnd = it->second.second.end ();
350 
351  if (it->second.first.m_inactivityEvent.IsRunning ())
352  {
353  /* Upon reception of a block ack frame, the inactivity timer at the
354  originator must be reset.
355  For more details see section 11.5.3 in IEEE802.11e standard */
356  it->second.first.m_inactivityEvent.Cancel ();
357  Time timeout = MicroSeconds (1024 * it->second.first.GetTimeout ());
358  it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
359  &BlockAckManager::InactivityTimeout,
360  this,
361  recipient, tid);
362  }
363  if (blockAck->IsBasic ())
364  {
365  for (PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd;)
366  {
367  if (blockAck->IsFragmentReceived ((*queueIt).hdr.GetSequenceNumber (),
368  (*queueIt).hdr.GetFragmentNumber ()))
369  {
370  queueIt = it->second.second.erase (queueIt);
371  }
372  else
373  {
374  if (!foundFirstLost)
375  {
376  foundFirstLost = true;
377  sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber ();
378  (*it).second.first.SetStartingSequence (sequenceFirstLost);
379  }
380  m_retryPackets.push_back (queueIt);
381  queueIt++;
382  }
383  }
384  }
385  else if (blockAck->IsCompressed ())
386  {
387  for (PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd;)
388  {
389  if (blockAck->IsPacketReceived ((*queueIt).hdr.GetSequenceNumber ()))
390  {
391  uint16_t currentSeq = (*queueIt).hdr.GetSequenceNumber ();
392  while (queueIt != queueEnd
393  && (*queueIt).hdr.GetSequenceNumber () == currentSeq)
394  {
395  queueIt = it->second.second.erase (queueIt);
396  }
397  }
398  else
399  {
400  if (!foundFirstLost)
401  {
402  foundFirstLost = true;
403  sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber ();
404  (*it).second.first.SetStartingSequence (sequenceFirstLost);
405  }
406  m_retryPackets.push_back (queueIt);
407  queueIt++;
408  }
409  }
410  }
411  uint16_t newSeq = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
412  if ((foundFirstLost && !SwitchToBlockAckIfNeeded (recipient, tid, sequenceFirstLost))
413  || (!foundFirstLost && !SwitchToBlockAckIfNeeded (recipient, tid, newSeq)))
414  {
415  it->second.first.SetState (OriginatorBlockAckAgreement::INACTIVE);
416  }
417  }
418  }
419  else
420  {
421  //NOT SUPPORTED FOR NOW
422  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
423  }
424 }
425 
426 void
427 BlockAckManager::SetBlockAckType (enum BlockAckType bAckType)
428 {
429  NS_LOG_FUNCTION (this << bAckType);
430  m_blockAckType = bAckType;
431 }
432 
435 {
436  /* This method checks if a BlockAckRequest frame should be send to the recipient station.
437  Number of packets under block ack is specified in OriginatorBlockAckAgreement object but sometimes
438  this number could be incorrect. In fact is possible that a block ack agreement exists for n
439  packets but some of these packets are dropped due to MSDU lifetime expiration.
440  */
441  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid));
442  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
443  NS_ASSERT (it != m_agreements.end ());
444 
445  if ((*it).second.first.IsBlockAckRequestNeeded ()
446  || (GetNRetryNeededPackets (recipient, tid) == 0
447  && m_queue->GetNPacketsByTidAndAddress (tid, WifiMacHeader::ADDR1, recipient) == 0))
448  {
449  OriginatorBlockAckAgreement &agreement = (*it).second.first;
450  agreement.CompleteExchange ();
451 
452  CtrlBAckRequestHeader reqHdr;
453  if (m_blockAckType == BASIC_BLOCK_ACK || m_blockAckType == COMPRESSED_BLOCK_ACK)
454  {
455  reqHdr.SetType (m_blockAckType);
456  reqHdr.SetTidInfo (agreement.GetTid ());
457  reqHdr.SetStartingSequence (agreement.GetStartingSequence ());
458  }
459  else if (m_blockAckType == MULTI_TID_BLOCK_ACK)
460  {
461  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
462  }
463  else
464  {
465  NS_FATAL_ERROR ("Invalid block ack type.");
466  }
467  Ptr<Packet> bar = Create<Packet> ();
468  bar->AddHeader (reqHdr);
469  return bar;
470  }
471  return 0;
472 }
473 
474 void
475 BlockAckManager::InactivityTimeout (Mac48Address recipient, uint8_t tid)
476 {
477  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid));
478  m_blockAckInactivityTimeout (recipient, tid, true);
479 }
480 
481 void
482 BlockAckManager::NotifyAgreementEstablished (Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
483 {
484  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid) << startingSeq);
485  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
486  NS_ASSERT (it != m_agreements.end ());
487 
488  it->second.first.SetState (OriginatorBlockAckAgreement::ESTABLISHED);
489  it->second.first.SetStartingSequence (startingSeq);
490 }
491 
492 void
494 {
495  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid));
496  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
497  NS_ASSERT (it != m_agreements.end ());
498  if (it != m_agreements.end ())
499  {
500  it->second.first.SetState (OriginatorBlockAckAgreement::UNSUCCESSFUL);
501  }
502 }
503 
504 void
505 BlockAckManager::NotifyMpduTransmission (Mac48Address recipient, uint8_t tid, uint16_t nextSeqNumber)
506 {
507  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid) << nextSeqNumber);
508  Ptr<Packet> bar = 0;
509  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
510  NS_ASSERT (it != m_agreements.end ());
511 
512  uint16_t nextSeq;
513  if (GetNRetryNeededPackets (recipient, tid) > 0)
514  {
515  nextSeq = GetSeqNumOfNextRetryPacket (recipient, tid);
516  }
517  else
518  {
519  nextSeq = nextSeqNumber;
520  }
521  it->second.first.NotifyMpduTransmission (nextSeq);
522  bar = ScheduleBlockAckReqIfNeeded (recipient, tid);
523  if (bar != 0)
524  {
525  Bar request (bar, recipient, tid, it->second.first.IsImmediateBlockAck ());
526  m_bars.push_back (request);
527  }
528 }
529 
530 void
532 {
533  NS_LOG_FUNCTION (this << queue);
534  m_queue = queue;
535 }
536 
537 bool
538 BlockAckManager::SwitchToBlockAckIfNeeded (Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
539 {
540  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid) << startingSeq);
541  NS_ASSERT (!ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::PENDING));
542  if (!ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::UNSUCCESSFUL) && ExistsAgreement (recipient, tid))
543  {
544  uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, WifiMacHeader::ADDR1, recipient) +
545  GetNBufferedPackets (recipient, tid);
546  if (packets >= m_blockAckThreshold)
547  {
548  NotifyAgreementEstablished (recipient, tid, startingSeq);
549  return true;
550  }
551  }
552  return false;
553 }
554 
555 void
557 {
558  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid));
559  DestroyAgreement (recipient, tid);
560 }
561 
562 bool
563 BlockAckManager::HasOtherFragments (uint16_t sequenceNumber) const
564 {
565  NS_LOG_FUNCTION (this << sequenceNumber);
566  bool retVal = false;
567  if (m_retryPackets.size () > 0)
568  {
569  Item next = *(m_retryPackets.front ());
570  if (next.hdr.GetSequenceNumber () == sequenceNumber)
571  {
572  retVal = true;
573  }
574  }
575  return retVal;
576 }
577 
578 uint32_t
580 {
581  NS_LOG_FUNCTION (this);
582  uint32_t size = 0;
583  if (m_retryPackets.size () > 0)
584  {
585  Item next = *(m_retryPackets.front ());
586  size = next.packet->GetSize ();
587  }
588  return size;
589 }
590 
591 void
593 {
594  NS_LOG_FUNCTION (this);
595  for (AgreementsI j = m_agreements.begin (); j != m_agreements.end (); j++)
596  {
597  if (j->second.second.empty ())
598  {
599  continue;
600  }
601  Time now = Simulator::Now ();
602  PacketQueueI end = j->second.second.begin ();
603  for (PacketQueueI i = j->second.second.begin (); i != j->second.second.end (); i++)
604  {
605  if (i->timestamp + m_maxDelay > now)
606  {
607  end = i;
608  break;
609  }
610  else
611  {
612  /* remove retry packet iterator if it's present in retry queue */
613  for (std::list<PacketQueueI>::iterator it = m_retryPackets.begin (); it != m_retryPackets.end ();)
614  {
615  if ((*it)->hdr.GetAddr1 () == j->second.first.GetPeer ()
616  && (*it)->hdr.GetQosTid () == j->second.first.GetTid ()
617  && (*it)->hdr.GetSequenceNumber () == i->hdr.GetSequenceNumber ())
618  {
619  it = m_retryPackets.erase (it);
620  }
621  else
622  {
623  it++;
624  }
625  }
626  }
627  }
628  j->second.second.erase (j->second.second.begin (), end);
629  j->second.first.SetStartingSequence (end->hdr.GetSequenceNumber ());
630  }
631 }
632 
633 void
635 {
636  NS_LOG_FUNCTION (this << maxDelay);
637  m_maxDelay = maxDelay;
638 }
639 
640 void
641 BlockAckManager::SetBlockAckInactivityCallback (Callback<void, Mac48Address, uint8_t, bool> callback)
642 {
643  NS_LOG_FUNCTION (this << &callback);
644  m_blockAckInactivityTimeout = callback;
645 }
646 
647 void
648 BlockAckManager::SetBlockDestinationCallback (Callback<void, Mac48Address, uint8_t> callback)
649 {
650  NS_LOG_FUNCTION (this << &callback);
651  m_blockPackets = callback;
652 }
653 
654 void
655 BlockAckManager::SetUnblockDestinationCallback (Callback<void, Mac48Address, uint8_t> callback)
656 {
657  NS_LOG_FUNCTION (this << &callback);
658  m_unblockPackets = callback;
659 }
660 
661 void
662 BlockAckManager::SetTxMiddle (MacTxMiddle* txMiddle)
663 {
664  NS_LOG_FUNCTION (this << txMiddle);
665  m_txMiddle = txMiddle;
666 }
667 
668 uint16_t
670 {
671  NS_LOG_FUNCTION (this << recipient << static_cast<uint32_t> (tid));
672  std::list<PacketQueueI>::const_iterator it = m_retryPackets.begin ();
673  while (it != m_retryPackets.end ())
674  {
675  if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
676  {
677  return (*it)->hdr.GetSequenceNumber ();
678  }
679  }
680  return 4096;
681 }
682 
683 } // namespace ns3
keep track of time unit.
Definition: nstime.h:149
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
Callback template class.
Definition: callback.h:369
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)
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
void SetBlockAckType(enum BlockAckType bAckType)
#define NS_LOG_INFO(msg)
Definition: log.h:264
bool HasPackets(void) const
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
Block Ack Request.
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
Ptr< Packet > ScheduleBlockAckReqIfNeeded(Mac48Address recipient, uint8_t tid)
void SetQueue(Ptr< WifiMacQueue > queue)
void NotifyAgreementEstablished(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
void UpdateAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address recipient)
uint32_t GetNRetryNeededPackets(Mac48Address recipient, uint8_t tid) const
uint32_t GetNextPacketSize(void) const
uint16_t GetSeqNumOfNextRetryPacket(Mac48Address recipient, uint8_t tid) const
void NotifyAgreementUnsuccessful(Mac48Address recipient, uint8_t tid)
bool HasOtherFragments(uint16_t sequenceNumber) const
std::list< PacketQueueI > m_retryPackets
Headers for Block ack response.
Definition: ctrl-headers.h:102
void DestroyAgreement(Mac48Address recipient, uint8_t tid)
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)
static Time Now(void)
Definition: simulator.cc:179
void SetMaxPacketDelay(Time maxDelay)
bool SwitchToBlockAckIfNeeded(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
uint32_t GetNBufferedPackets(Mac48Address recipient, uint8_t tid) const
void SetBlockAckThreshold(uint8_t nPackets)
Headers for Block ack request.
Definition: ctrl-headers.h:46
bool ExistsAgreement(Mac48Address recipient, uint8_t tid) const
Time MicroSeconds(uint64_t us)
create ns3::Time instances in units of microseconds.
Definition: nstime.h:615
void NotifyMpduTransmission(Mac48Address recipient, uint8_t tid, uint16_t nextSeqNumber)
void AddHeader(const Header &header)
Definition: packet.cc:270
void TearDownBlockAck(Mac48Address recipient, uint8_t tid)