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 }
41 
43  : packet (packet),
44  hdr (hdr),
45  timestamp (tStamp)
46 {
47 }
48 
50 {
51 }
52 
53 Bar::Bar (Ptr<const Packet> bar, Mac48Address recipient, uint8_t tid, bool immediate)
54  : bar (bar),
55  recipient (recipient),
56  tid (tid),
57  immediate (immediate)
58 {
59 }
60 
62 {
63 }
64 
66 {
67  m_queue = 0;
68  m_agreements.clear ();
69  m_retryPackets.clear ();
70 }
71 
72 bool
73 BlockAckManager::ExistsAgreement (Mac48Address recipient, uint8_t tid) const
74 {
75  return (m_agreements.find (std::make_pair (recipient, tid)) != m_agreements.end ());
76 }
77 
78 bool
80  enum OriginatorBlockAckAgreement::State state) const
81 {
82  AgreementsCI it;
83  it = m_agreements.find (std::make_pair (recipient, tid));
84  if (it != m_agreements.end ())
85  {
86  switch (state)
87  {
89  return it->second.first.IsInactive ();
91  return it->second.first.IsEstablished ();
93  return it->second.first.IsPending ();
95  return it->second.first.IsUnsuccessful ();
96  default:
97  NS_FATAL_ERROR ("Invalid state for block ack agreement");
98  }
99  }
100  return false;
101 }
102 
103 void
105 {
106  std::pair<Mac48Address, uint8_t> key (recipient, reqHdr->GetTid ());
107  OriginatorBlockAckAgreement agreement (recipient, reqHdr->GetTid ());
108  agreement.SetStartingSequence (reqHdr->GetStartingSequence ());
109  /* for now we assume that originator doesn't use this field. Use of this field
110  is mandatory only for recipient */
111  agreement.SetBufferSize (0);
112  agreement.SetTimeout (reqHdr->GetTimeout ());
113  agreement.SetAmsduSupport (reqHdr->IsAmsduSupported ());
114  if (reqHdr->IsImmediateBlockAck ())
115  {
116  agreement.SetImmediateBlockAck ();
117  }
118  else
119  {
120  agreement.SetDelayedBlockAck ();
121  }
122  agreement.SetState (OriginatorBlockAckAgreement::PENDING);
123  PacketQueue queue (0);
124  std::pair<OriginatorBlockAckAgreement, PacketQueue> value (agreement, queue);
125  m_agreements.insert (std::make_pair (key, value));
126  m_blockPackets (recipient, reqHdr->GetTid ());
127 }
128 
129 void
131 {
132  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
133  if (it != m_agreements.end ())
134  {
135  for (std::list<PacketQueueI>::iterator i = m_retryPackets.begin (); i != m_retryPackets.end ();)
136  {
137  if ((*i)->hdr.GetAddr1 () == recipient && (*i)->hdr.GetQosTid () == tid)
138  {
139  i = m_retryPackets.erase (i);
140  }
141  else
142  {
143  i++;
144  }
145  }
146  m_agreements.erase (it);
147  //remove scheduled bar
148  for (std::list<Bar>::iterator i = m_bars.begin (); i != m_bars.end ();)
149  {
150  if (i->recipient == recipient && i->tid == tid)
151  {
152  i = m_bars.erase (i);
153  }
154  else
155  {
156  i++;
157  }
158  }
159  }
160 }
161 
162 void
164 {
165  uint8_t tid = respHdr->GetTid ();
166  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
167  if (it != m_agreements.end ())
168  {
169  OriginatorBlockAckAgreement& agreement = it->second.first;
170  agreement.SetBufferSize (respHdr->GetBufferSize () + 1);
171  agreement.SetTimeout (respHdr->GetTimeout ());
172  agreement.SetAmsduSupport (respHdr->IsAmsduSupported ());
173  if (respHdr->IsImmediateBlockAck ())
174  {
175  agreement.SetImmediateBlockAck ();
176  }
177  else
178  {
179  agreement.SetDelayedBlockAck ();
180  }
182  if (agreement.GetTimeout () != 0)
183  {
184  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
185  agreement.m_inactivityEvent = Simulator::Schedule (timeout,
187  this,
188  recipient, tid);
189  }
190  }
191  m_unblockPackets (recipient, tid);
192 }
193 
194 void
196 {
197  NS_LOG_FUNCTION (this);
198  NS_ASSERT (hdr.IsQosData ());
199 
200  uint8_t tid = hdr.GetQosTid ();
201  Mac48Address recipient = hdr.GetAddr1 ();
202 
203  Item item (packet, hdr, tStamp);
204  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
205  NS_ASSERT (it != m_agreements.end ());
206  it->second.second.push_back (item);
207 }
208 
211 {
212  NS_LOG_FUNCTION (this);
213  Ptr<const Packet> packet = 0;
214  if (m_retryPackets.size () > 0)
215  {
216  CleanupBuffers ();
217  PacketQueueI queueIt = m_retryPackets.front ();
218  m_retryPackets.pop_front ();
219  packet = queueIt->packet;
220  hdr = queueIt->hdr;
221  hdr.SetRetry ();
222  NS_LOG_INFO ("Retry packet seq=" << hdr.GetSequenceNumber ());
223  uint8_t tid = hdr.GetQosTid ();
224  Mac48Address recipient = hdr.GetAddr1 ();
225 
227  || SwitchToBlockAckIfNeeded (recipient, tid, hdr.GetSequenceNumber ()))
228  {
230  }
231  else
232  {
233  /* From section 9.10.3 in IEEE802.11e standard:
234  * In order to improve efficiency, originators using the Block Ack facility
235  * may send MPDU frames with the Ack Policy subfield in QoS control frames
236  * set to Normal Ack if only a few MPDUs are available for transmission.[...]
237  * When there are sufficient number of MPDUs, the originator may switch back to
238  * the use of Block Ack.
239  */
241  AgreementsI i = m_agreements.find (std::make_pair (recipient, tid));
242  i->second.second.erase (queueIt);
243  }
244  }
245  return packet;
246 }
247 
248 bool
250 {
251  if (m_bars.size () > 0)
252  {
253  bar = m_bars.front ();
254  m_bars.pop_front ();
255  return true;
256  }
257  return false;
258 }
259 
260 bool
262 {
263  return (m_retryPackets.size () > 0 || m_bars.size () > 0);
264 }
265 
266 uint32_t
268 {
269  uint32_t nPackets = 0;
270  if (ExistsAgreement (recipient, tid))
271  {
272  AgreementsCI it = m_agreements.find (std::make_pair (recipient, tid));
273  PacketQueueCI queueIt = (*it).second.second.begin ();
274  uint16_t currentSeq = 0;
275  while (queueIt != (*it).second.second.end ())
276  {
277  currentSeq = (*queueIt).hdr.GetSequenceNumber ();
278  nPackets++;
279  /* a fragmented packet must be counted as one packet */
280  while (queueIt != (*it).second.second.end () && (*queueIt).hdr.GetSequenceNumber () == currentSeq)
281  {
282  queueIt++;
283  }
284  }
285  return nPackets;
286  }
287  return 0;
288 }
289 
290 uint32_t
292 {
293  uint32_t nPackets = 0;
294  uint16_t currentSeq = 0;
295  if (ExistsAgreement (recipient, tid))
296  {
297  std::list<PacketQueueI>::const_iterator it = m_retryPackets.begin ();
298  while (it != m_retryPackets.end ())
299  {
300  if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
301  {
302  currentSeq = (*it)->hdr.GetSequenceNumber ();
303  nPackets++;
304  /* a fragmented packet must be counted as one packet */
305  while (it != m_retryPackets.end () && (*it)->hdr.GetSequenceNumber () == currentSeq)
306  {
307  it++;
308  }
309  }
310  }
311  }
312  return nPackets;
313 }
314 
315 void
317 {
318  m_blockAckThreshold = nPackets;
319 }
320 
321 void
323 {
324  NS_LOG_FUNCTION (this);
325  uint16_t sequenceFirstLost = 0;
326  if (!blockAck->IsMultiTid ())
327  {
328  uint8_t tid = blockAck->GetTidInfo ();
330  {
331  bool foundFirstLost = false;
332  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
333  PacketQueueI queueEnd = it->second.second.end ();
334 
335  if (it->second.first.m_inactivityEvent.IsRunning ())
336  {
337  /* Upon reception of a block ack frame, the inactivity timer at the
338  originator must be reset.
339  For more details see section 11.5.3 in IEEE802.11e standard */
340  it->second.first.m_inactivityEvent.Cancel ();
341  Time timeout = MicroSeconds (1024 * it->second.first.GetTimeout ());
342  it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
344  this,
345  recipient, tid);
346  }
347  if (blockAck->IsBasic ())
348  {
349  for (PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd;)
350  {
351  if (blockAck->IsFragmentReceived ((*queueIt).hdr.GetSequenceNumber (),
352  (*queueIt).hdr.GetFragmentNumber ()))
353  {
354  queueIt = it->second.second.erase (queueIt);
355  }
356  else
357  {
358  if (!foundFirstLost)
359  {
360  foundFirstLost = true;
361  sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber ();
362  (*it).second.first.SetStartingSequence (sequenceFirstLost);
363  }
364  m_retryPackets.push_back (queueIt);
365  queueIt++;
366  }
367  }
368  }
369  else if (blockAck->IsCompressed ())
370  {
371  for (PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd;)
372  {
373  if (blockAck->IsPacketReceived ((*queueIt).hdr.GetSequenceNumber ()))
374  {
375  uint16_t currentSeq = (*queueIt).hdr.GetSequenceNumber ();
376  while (queueIt != queueEnd
377  && (*queueIt).hdr.GetSequenceNumber () == currentSeq)
378  {
379  queueIt = it->second.second.erase (queueIt);
380  }
381  }
382  else
383  {
384  if (!foundFirstLost)
385  {
386  foundFirstLost = true;
387  sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber ();
388  (*it).second.first.SetStartingSequence (sequenceFirstLost);
389  }
390  m_retryPackets.push_back (queueIt);
391  queueIt++;
392  }
393  }
394  }
395  uint16_t newSeq = m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
396  if ((foundFirstLost && !SwitchToBlockAckIfNeeded (recipient, tid, sequenceFirstLost))
397  || (!foundFirstLost && !SwitchToBlockAckIfNeeded (recipient, tid, newSeq)))
398  {
399  it->second.first.SetState (OriginatorBlockAckAgreement::INACTIVE);
400  }
401  }
402  }
403  else
404  {
405  //NOT SUPPORTED FOR NOW
406  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
407  }
408 }
409 
410 void
412 {
413  m_blockAckType = bAckType;
414 }
415 
418 {
419  /* This method checks if a BlockAckRequest frame should be send to the recipient station.
420  Number of packets under block ack is specified in OriginatorBlockAckAgreement object but sometimes
421  this number could be incorrect. In fact is possible that a block ack agreement exists for n
422  packets but some of these packets are dropped due to MSDU lifetime expiration.
423  */
424  NS_LOG_FUNCTION (this);
425  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
426  NS_ASSERT (it != m_agreements.end ());
427 
428  if ((*it).second.first.IsBlockAckRequestNeeded ()
429  || (GetNRetryNeededPackets (recipient, tid) == 0
430  && m_queue->GetNPacketsByTidAndAddress (tid, WifiMacHeader::ADDR1, recipient) == 0))
431  {
432  OriginatorBlockAckAgreement &agreement = (*it).second.first;
433  agreement.CompleteExchange ();
434 
435  CtrlBAckRequestHeader reqHdr;
437  {
438  reqHdr.SetType (m_blockAckType);
439  reqHdr.SetTidInfo (agreement.GetTid ());
440  reqHdr.SetStartingSequence (agreement.GetStartingSequence ());
441  }
443  {
444  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
445  }
446  else
447  {
448  NS_FATAL_ERROR ("Invalid block ack type.");
449  }
450  Ptr<Packet> bar = Create<Packet> ();
451  bar->AddHeader (reqHdr);
452  return bar;
453  }
454  return 0;
455 }
456 
457 void
459 {
460  m_blockAckInactivityTimeout (recipient, tid, true);
461 }
462 
463 void
464 BlockAckManager::NotifyAgreementEstablished (Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
465 {
466  NS_LOG_FUNCTION (this);
467  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
468  NS_ASSERT (it != m_agreements.end ());
469 
470  it->second.first.SetState (OriginatorBlockAckAgreement::ESTABLISHED);
471  it->second.first.SetStartingSequence (startingSeq);
472 }
473 
474 void
476 {
477  NS_LOG_FUNCTION (this);
478  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
479  NS_ASSERT (it != m_agreements.end ());
480  if (it != m_agreements.end ())
481  {
482  it->second.first.SetState (OriginatorBlockAckAgreement::UNSUCCESSFUL);
483  }
484 }
485 
486 void
487 BlockAckManager::NotifyMpduTransmission (Mac48Address recipient, uint8_t tid, uint16_t nextSeqNumber)
488 {
489  NS_LOG_FUNCTION (this);
490  Ptr<Packet> bar = 0;
491  AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
492  NS_ASSERT (it != m_agreements.end ());
493 
494  uint16_t nextSeq;
495  if (GetNRetryNeededPackets (recipient, tid) > 0)
496  {
497  nextSeq = GetSeqNumOfNextRetryPacket (recipient, tid);
498  }
499  else
500  {
501  nextSeq = nextSeqNumber;
502  }
503  it->second.first.NotifyMpduTransmission (nextSeq);
504  bar = ScheduleBlockAckReqIfNeeded (recipient, tid);
505  if (bar != 0)
506  {
507  Bar request (bar, recipient, tid, it->second.first.IsImmediateBlockAck ());
508  m_bars.push_back (request);
509  }
510 }
511 
512 void
514 {
515  m_queue = queue;
516 }
517 
518 bool
519 BlockAckManager::SwitchToBlockAckIfNeeded (Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
520 {
521  NS_LOG_FUNCTION (this);
523  if (!ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::UNSUCCESSFUL) && ExistsAgreement (recipient, tid))
524  {
525  uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, WifiMacHeader::ADDR1, recipient) +
526  GetNBufferedPackets (recipient, tid);
527  if (packets >= m_blockAckThreshold)
528  {
529  NotifyAgreementEstablished (recipient, tid, startingSeq);
530  return true;
531  }
532  }
533  return false;
534 }
535 
536 void
538 {
539  NS_LOG_FUNCTION (this);
540  DestroyAgreement (recipient, tid);
541 }
542 
543 bool
544 BlockAckManager::HasOtherFragments (uint16_t sequenceNumber) const
545 {
546  bool retVal = false;
547  if (m_retryPackets.size () > 0)
548  {
549  Item next = *(m_retryPackets.front ());
550  if (next.hdr.GetSequenceNumber () == sequenceNumber)
551  {
552  retVal = true;
553  }
554  }
555  return retVal;
556 }
557 
558 uint32_t
560 {
561  uint32_t size = 0;
562  if (m_retryPackets.size () > 0)
563  {
564  Item next = *(m_retryPackets.front ());
565  size = next.packet->GetSize ();
566  }
567  return size;
568 }
569 
570 void
572 {
573  for (AgreementsI j = m_agreements.begin (); j != m_agreements.end (); j++)
574  {
575  if (j->second.second.empty ())
576  {
577  continue;
578  }
579  Time now = Simulator::Now ();
580  PacketQueueI end = j->second.second.begin ();
581  for (PacketQueueI i = j->second.second.begin (); i != j->second.second.end (); i++)
582  {
583  if (i->timestamp + m_maxDelay > now)
584  {
585  end = i;
586  break;
587  }
588  else
589  {
590  /* remove retry packet iterator if it's present in retry queue */
591  for (std::list<PacketQueueI>::iterator it = m_retryPackets.begin (); it != m_retryPackets.end (); it++)
592  {
593  if ((*it)->hdr.GetAddr1 () == j->second.first.GetPeer ()
594  && (*it)->hdr.GetQosTid () == j->second.first.GetTid ()
595  && (*it)->hdr.GetSequenceNumber () == i->hdr.GetSequenceNumber ())
596  {
597  m_retryPackets.erase (it);
598  }
599  }
600  }
601  }
602  j->second.second.erase (j->second.second.begin (), end);
603  j->second.first.SetStartingSequence (end->hdr.GetSequenceNumber ());
604  }
605 }
606 
607 void
609 {
610  NS_LOG_FUNCTION (this);
611  m_maxDelay = maxDelay;
612 }
613 
614 void
616 {
617  m_blockAckInactivityTimeout = callback;
618 }
619 
620 void
622 {
623  m_blockPackets = callback;
624 }
625 
626 void
628 {
629  m_unblockPackets = callback;
630 }
631 
632 void
634 {
635  m_txMiddle = txMiddle;
636 }
637 
638 uint16_t
640 {
641  std::list<PacketQueueI>::const_iterator it = m_retryPackets.begin ();
642  while (it != m_retryPackets.end ())
643  {
644  if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
645  {
646  return (*it)->hdr.GetSequenceNumber ();
647  }
648  }
649  return 4096;
650 }
651 
652 } // namespace ns3