A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
block-ack-manager.cc
Go to the documentation of this file.
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 
39 {
40  NS_LOG_FUNCTION (this);
41 }
42 
44  : packet (packet),
45  hdr (hdr),
46  timestamp (tStamp)
47 {
48  NS_LOG_FUNCTION (this << packet << hdr << tStamp);
49 }
50 
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 
66 {
67  NS_LOG_FUNCTION (this);
68 }
69 
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  {
97  return it->second.first.IsInactive ();
99  return it->second.first.IsEstablished ();
101  return it->second.first.IsPending ();
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  }
193  if (agreement.GetTimeout () != 0)
194  {
195  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
196  agreement.m_inactivityEvent = Simulator::Schedule (timeout,
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 
238  || SwitchToBlockAckIfNeeded (recipient, tid, hdr.GetSequenceNumber ()))
239  {
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  */
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
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 ();
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,
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
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;
454  {
455  reqHdr.SetType (m_blockAckType);
456  reqHdr.SetTidInfo (agreement.GetTid ());
457  reqHdr.SetStartingSequence (agreement.GetStartingSequence ());
458  }
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
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);
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
642 {
643  NS_LOG_FUNCTION (this << &callback);
644  m_blockAckInactivityTimeout = callback;
645 }
646 
647 void
649 {
650  NS_LOG_FUNCTION (this << &callback);
651  m_blockPackets = callback;
652 }
653 
654 void
656 {
657  NS_LOG_FUNCTION (this << &callback);
658  m_unblockPackets = callback;
659 }
660 
661 void
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
void SetRetry(void)
Set the Retry bit in the Frame Control field.
void SetUnblockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
uint16_t GetBufferSize(void) const
Return the buffer size.
Definition: mgt-headers.cc:953
uint8_t GetTid(void) const
Return the Traffic ID (TID).
void SetType(enum BlockAckType type)
Set the block ACK type.
keep track of time values and allow control of global simulation resolution
Definition: nstime.h:81
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:345
void SetQosAckPolicy(enum QosAckPolicy policy)
Set the QoS ACK policy in the QoS control field.
Callback template class.
Definition: callback.h:920
std::list< Item > PacketQueue
typedef for a list of Item struct.
Maintains the state and information about transmitted MPDUs with ack policy block ack for an originat...
uint16_t GetTimeout(void) const
Return the timeout.
void NotifyGotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address recipient)
std::map< std::pair< Mac48Address, uint8_t >, std::pair< OriginatorBlockAckAgreement, PacketQueue > >::const_iterator AgreementsCI
typedef for a const iterator for Agreements.
void CreateAgreement(const MgtAddBaRequestHeader *reqHdr, Mac48Address recipient)
void StorePacket(Ptr< const Packet > packet, const WifiMacHeader &hdr, Time tStamp)
Agreements m_agreements
This data structure contains, for each block ack agreement (recipient, tid), a set of packets for whi...
Implement the header for management frames of type add block ack request.
Definition: mgt-headers.h:454
bool IsImmediateBlockAck(void) const
Return whether the Block ACK policy is immediate Block ACK.
Definition: mgt-headers.cc:941
#define NS_ASSERT(condition)
Definition: assert.h:64
bool HasBar(struct Bar &bar)
bool IsPacketReceived(uint16_t seq) const
Check if the packet with the given sequence number was ACKed in this Block ACK response.
uint32_t GetSize(void) const
Definition: packet.h:650
void InactivityTimeout(Mac48Address, uint8_t)
std::map< std::pair< Mac48Address, uint8_t >, std::pair< OriginatorBlockAckAgreement, PacketQueue > >::iterator AgreementsI
typedef for an iterator for Agreements.
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
void SetBlockAckType(enum BlockAckType bAckType)
#define NS_LOG_INFO(msg)
Definition: log.h:298
bool HasPackets(void) const
Returns true if there are packets that need of retransmission or at least a BAR is scheduled...
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:824
ns3::Time timeout
BlockAckType
Enumeration for different block ACK policies.
Definition: ctrl-headers.h:30
Block Ack Request.
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
uint16_t GetStartingSequence(void) const
Return the starting squence number.
Handles sequence numbering of IEEE 802.11 data frames.
Definition: mac-tx-middle.h:39
bool IsAmsduSupported(void) const
Return whether A-MSDU capability is supported.
Definition: mgt-headers.cc:959
Ptr< Packet > ScheduleBlockAckReqIfNeeded(Mac48Address recipient, uint8_t tid)
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
void SetQueue(Ptr< WifiMacQueue > queue)
void NotifyAgreementEstablished(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
NS_LOG_COMPONENT_DEFINE("BlockAckManager")
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
This list contains all iterators to stored packets that need to be retransmitted. ...
Headers for Block ack response.
Definition: ctrl-headers.h:183
void SetTxMiddle(MacTxMiddle *txMiddle)
bool IsFragmentReceived(uint16_t seq, uint8_t frag) const
Check if the packet with the given sequence number and fragment number was ACKed in this Block ACK re...
void SetBlockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
void DestroyAgreement(Mac48Address recipient, uint8_t tid)
uint8_t GetTid(void) const
Return the Traffic ID (TID).
Definition: mgt-headers.cc:750
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
bool IsAmsduSupported(void) const
Return whether A-MSDU capability is supported.
Definition: mgt-headers.cc:774
Callback< void, Mac48Address, uint8_t, bool > m_blockAckInactivityTimeout
bool IsBasic(void) const
Check if the current ACK policy is basic (i.e.
bool ExistsAgreementInState(Mac48Address recipient, uint8_t tid, enum OriginatorBlockAckAgreement::State state) const
Callback< void, Mac48Address, uint8_t > m_blockPackets
an EUI-48 address
Definition: mac48-address.h:41
Ptr< const Packet > GetNextPacket(WifiMacHeader &hdr)
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
State
Represents the state for this agreement.
void SetBlockAckInactivityCallback(Callback< void, Mac48Address, uint8_t, bool > callback)
uint16_t GetTimeout(void) const
Return the timeout.
Definition: mgt-headers.cc:947
uint8_t GetTid(void) const
Return the Traffic ID (TID).
Definition: mgt-headers.cc:935
void SetMaxPacketDelay(Time maxDelay)
bool IsImmediateBlockAck(void) const
Return whether the Block ACK policy is immediate Block ACK.
Definition: mgt-headers.cc:756
void SetDelayedBlockAck(void)
Set Block ACK policy to delayed ACK.
void SetAmsduSupport(bool supported)
Enable or disable A-MSDU support.
A struct for packet, Wifi header, and timestamp.
bool SwitchToBlockAckIfNeeded(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
std::list< Item >::const_iterator PacketQueueCI
typedef for a const iterator for PacketQueue.
Callback< void, Mac48Address, uint8_t > m_unblockPackets
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
Definition: mgt-headers.cc:780
uint32_t GetNBufferedPackets(Mac48Address recipient, uint8_t tid) const
std::list< Bar > m_bars
enum BlockAckType m_blockAckType
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS DATA...
void CleanupBuffers(void)
This method removes packets whose lifetime was exceeded.
void SetBlockAckThreshold(uint8_t nPackets)
Implement the header for management frames of type add block ack response.
Definition: mgt-headers.h:582
void SetImmediateBlockAck(void)
Set Block ACK policy to immediate ACK.
void SetTimeout(uint16_t timeout)
Set timeout.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
Headers for Block ack request.
Definition: ctrl-headers.h:49
bool ExistsAgreement(Mac48Address recipient, uint8_t tid) const
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
uint16_t GetNextSeqNumberByTidAndAddress(uint8_t tid, Mac48Address addr) const
Return the next sequence number for the Traffic ID and destination.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
bool IsMultiTid(void) const
Check if the current ACK policy has multiple TID.
Ptr< const Packet > packet
void NotifyMpduTransmission(Mac48Address recipient, uint8_t tid, uint16_t nextSeqNumber)
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
Implements the IEEE 802.11 MAC header.
void TearDownBlockAck(Mac48Address recipient, uint8_t tid)
Ptr< WifiMacQueue > m_queue
uint16_t GetTimeout(void) const
Return the timeout.
Definition: mgt-headers.cc:762
std::list< Item >::iterator PacketQueueI
typedef for an iterator for PacketQueue.
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.