A Discrete-Event Network Simulator
API
mac-low.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 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  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  * Mirko Banchi <mk.banchi@gmail.com>
21  */
22 
23 #include "ns3/assert.h"
24 #include "ns3/packet.h"
25 #include "ns3/simulator.h"
26 #include "ns3/tag.h"
27 #include "ns3/log.h"
28 #include "ns3/node.h"
29 #include "ns3/double.h"
30 #include "mac-low.h"
31 #include "wifi-phy.h"
32 #include "wifi-mac-trailer.h"
33 #include "qos-utils.h"
34 #include "edca-txop-n.h"
35 #include "snr-tag.h"
36 #include "yans-wifi-phy.h"
37 #include "ampdu-tag.h"
38 #include "wifi-mac-queue.h"
39 
40 #undef NS_LOG_APPEND_CONTEXT
41 #define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_self << "] "
42 
43 namespace ns3 {
44 
45 NS_LOG_COMPONENT_DEFINE ("MacLow");
46 
48 {
49 }
51 {
52 }
53 void
54 MacLowTransmissionListener::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address source, double rxSnr, WifiMode mode, double dataSnr)
55 {
56 }
57 void
59 {
60 }
61 
63 {
64 }
66 {
67 }
68 
70 {
71 }
73 {
74 }
76 {
77 }
79 {
80 }
81 void
83 {
84 }
85 uint16_t
87 {
88  return 0;
89 }
90 uint16_t
92 {
93  return 0;
94 }
97 {
98  return 0;
99 }
100 void
102 {
103 }
104 uint32_t
106 {
107  return 0;
108 }
109 uint32_t
111 {
112  return 0;
113 }
116 {
117  return 0;
118 }
121 {
122  return 0;
123 }
126 {
127  return 0;
128 }
131 {
132  return 0;
133 }
134 
136  : m_nextSize (0),
137  m_waitAck (ACK_NONE),
138  m_sendRts (false),
139  m_overrideDurationId (Seconds (0))
140 {
141 }
142 void
144 {
145  m_nextSize = size;
146 }
147 void
149 {
150  m_nextSize = 0;
151 }
152 void
154 {
155  m_overrideDurationId = durationId;
156 }
157 void
159 {
161 }
162 void
164 {
166 }
167 void
169 {
171 }
172 void
174 {
176 }
177 void
179 {
181 }
182 void
184 {
186 }
187 void
189 {
191 }
192 void
194 {
196 }
197 void
199 {
200  m_sendRts = true;
201 }
202 void
204 {
205  m_sendRts = false;
206 }
207 bool
209 {
210  return (m_waitAck != ACK_NONE);
211 }
212 bool
214 {
215  return (m_waitAck == ACK_NORMAL);
216 }
217 bool
219 {
220  return (m_waitAck == ACK_FAST);
221 }
222 bool
224 {
225  return (m_waitAck == ACK_SUPER_FAST);
226 }
227 bool
229 {
230  return (m_waitAck == BLOCK_ACK_BASIC) ? true : false;
231 }
232 bool
234 {
235  return (m_waitAck == BLOCK_ACK_COMPRESSED) ? true : false;
236 }
237 bool
239 {
240  return (m_waitAck == BLOCK_ACK_MULTI_TID) ? true : false;
241 }
242 bool
244 {
245  return m_sendRts;
246 }
247 bool
249 {
250  return (m_overrideDurationId != Seconds (0));
251 }
252 Time
254 {
256  return m_overrideDurationId;
257 }
258 bool
260 {
261  return (m_nextSize != 0);
262 }
263 uint32_t
265 {
267  return m_nextSize;
268 }
269 
270 std::ostream &operator << (std::ostream &os, const MacLowTransmissionParameters &params)
271 {
272  os << "["
273  << "send rts=" << params.m_sendRts << ", "
274  << "next size=" << params.m_nextSize << ", "
275  << "dur=" << params.m_overrideDurationId << ", "
276  << "ack=";
277  switch (params.m_waitAck)
278  {
280  os << "none";
281  break;
283  os << "normal";
284  break;
286  os << "fast";
287  break;
289  os << "super-fast";
290  break;
292  os << "basic-block-ack";
293  break;
295  os << "compressed-block-ack";
296  break;
298  os << "multi-tid-block-ack";
299  break;
300  }
301  os << "]";
302  return os;
303 }
304 
305 
310 {
311 public:
318  : m_macLow (macLow)
319  {
320  }
322  {
323  }
324  virtual void NotifyRxStart (Time duration)
325  {
326  }
327  virtual void NotifyRxEndOk (void)
328  {
329  }
330  virtual void NotifyRxEndError (void)
331  {
332  }
333  virtual void NotifyTxStart (Time duration, double txPowerDbm)
334  {
335  }
336  virtual void NotifyMaybeCcaBusyStart (Time duration)
337  {
338  }
339  virtual void NotifySwitchingStart (Time duration)
340  {
341  m_macLow->NotifySwitchingStartNow (duration);
342  }
343  virtual void NotifySleep (void)
344  {
346  }
347  virtual void NotifyWakeup (void)
348  {
349  }
350 private:
352 };
353 
354 
356  : m_normalAckTimeoutEvent (),
357  m_fastAckTimeoutEvent (),
358  m_superFastAckTimeoutEvent (),
359  m_fastAckFailedTimeoutEvent (),
360  m_blockAckTimeoutEvent (),
361  m_ctsTimeoutEvent (),
362  m_sendCtsEvent (),
363  m_sendAckEvent (),
364  m_sendDataEvent (),
365  m_waitSifsEvent (),
366  m_endTxNoAckEvent (),
367  m_currentPacket (0),
368  m_listener (0),
369  m_phyMacLowListener (0),
370  m_ctsToSelfSupported (false),
371  m_receivedAtLeastOneMpdu (false),
372  m_nTxMpdus (0)
373 {
374  NS_LOG_FUNCTION (this);
376  m_lastNavStart = Seconds (0);
377  m_promisc = false;
378  m_ampdu = false;
379  m_sentMpdus = 0;
380  m_aggregateQueue = CreateObject<WifiMacQueue> ();
381 }
382 
384 {
385  NS_LOG_FUNCTION (this);
386 }
387 
388 /* static */
389 TypeId
391 {
392  static TypeId tid = TypeId ("ns3::MacLow")
393  .SetParent<Object> ()
394  .SetGroupName ("Wifi")
395  .AddConstructor<MacLow> ()
396  ;
397  return tid;
398 }
399 
400 void
402 {
405 }
406 
407 void
409 {
410  if (m_phyMacLowListener != 0 )
411  {
413  delete m_phyMacLowListener;
415  }
416 }
417 
418 void
420 {
421  NS_LOG_FUNCTION (this);
434  m_phy = 0;
435  m_stationManager = 0;
436  if (m_phyMacLowListener != 0)
437  {
438  delete m_phyMacLowListener;
440  }
441  m_sentMpdus = 0;
442  m_aggregateQueue = 0;
443  m_ampdu = false;
444 }
445 
446 void
448 {
449  NS_LOG_FUNCTION (this);
450  bool oneRunning = false;
452  {
454  oneRunning = true;
455  }
457  {
459  oneRunning = true;
460  }
462  {
464  oneRunning = true;
465  }
467  {
469  oneRunning = true;
470  }
472  {
474  oneRunning = true;
475  }
477  {
479  oneRunning = true;
480  }
481  if (m_sendCtsEvent.IsRunning ())
482  {
484  oneRunning = true;
485  }
486  if (m_sendAckEvent.IsRunning ())
487  {
489  oneRunning = true;
490  }
491  if (m_sendDataEvent.IsRunning ())
492  {
494  oneRunning = true;
495  }
496  if (m_waitSifsEvent.IsRunning ())
497  {
499  oneRunning = true;
500  }
501  if (m_waitRifsEvent.IsRunning ())
502  {
504  oneRunning = true;
505  }
507  {
509  oneRunning = true;
510  }
511  if (oneRunning && m_listener != 0)
512  {
513  m_listener->Cancel ();
514  m_listener = 0;
515  }
516 }
517 
518 void
520 {
521  m_phy = phy;
525 }
526 
528 MacLow::GetPhy (void) const
529 {
530  return m_phy;
531 }
532 
533 void
535 {
537  m_phy->SetReceiveErrorCallback (MakeNullCallback<void, Ptr<Packet>, double, bool> ());
539  m_phy = 0;
540 }
541 
542 void
544 {
545  m_stationManager = manager;
546 }
547 
548 void
550 {
551  m_self = ad;
552 }
553 
554 void
556 {
557  m_ackTimeout = ackTimeout;
558 }
559 
560 void
562 {
563  m_basicBlockAckTimeout = blockAckTimeout;
564 }
565 
566 void
568 {
569  m_compressedBlockAckTimeout = blockAckTimeout;
570 }
571 
572 void
574 {
575  m_ctsToSelfSupported = enable;
576 }
577 
578 bool
580 {
581  return m_ctsToSelfSupported;
582 }
583 
584 void
586 {
587  m_ctsTimeout = ctsTimeout;
588 }
589 
590 void
592 {
593  m_sifs = sifs;
594 }
595 
596 void
598 {
599  m_slotTime = slotTime;
600 }
601 
602 void
604 {
605  m_pifs = pifs;
606 }
607 
608 void
610 {
611  m_rifs = rifs;
612 }
613 
614 void
616 {
617  m_bssid = bssid;
618 }
619 
620 void
622 {
623  m_promisc = true;
624 }
625 
627 MacLow::GetAddress (void) const
628 {
629  return m_self;
630 }
631 
632 Time
634 {
635  return m_ackTimeout;
636 }
637 
638 Time
640 {
641  return m_basicBlockAckTimeout;
642 }
643 
644 Time
646 {
648 }
649 
650 Time
652 {
653  return m_ctsTimeout;
654 }
655 
656 Time
657 MacLow::GetSifs (void) const
658 {
659  return m_sifs;
660 }
661 
662 Time
663 MacLow::GetRifs (void) const
664 {
665  return m_rifs;
666 }
667 
668 Time
670 {
671  return m_slotTime;
672 }
673 
674 Time
675 MacLow::GetPifs (void) const
676 {
677  return m_pifs;
678 }
679 
681 MacLow::GetBssid (void) const
682 {
683  return m_bssid;
684 }
685 
686 bool
687 MacLow::IsPromisc (void) const
688 {
689  return m_promisc;
690 }
691 
692 void
694 {
695  m_rxCallback = callback;
696 }
697 
698 void
700 {
701  m_dcfListeners.push_back (listener);
702 }
703 
704 bool
706 {
707  uint32_t size, actualSize;
708  WifiMacTrailer fcs;
709  size = packet->GetSize () + hdr.GetSize () + fcs.GetSerializedSize ();
710  Ptr<Packet> p = AggregateToAmpdu (packet, hdr);
711  actualSize = p->GetSize ();
712  if (actualSize > size)
713  {
714  m_currentPacket = p;
715  return true;
716  }
717  else
718  {
719  return false;
720  }
721 }
722 
723 void
725  const WifiMacHeader* hdr,
727  MacLowTransmissionListener *listener)
728 {
729  NS_LOG_FUNCTION (this << packet << hdr << params << listener);
730  /* m_currentPacket is not NULL because someone started
731  * a transmission and was interrupted before one of:
732  * - ctsTimeout
733  * - sendDataAfterCTS
734  * expired. This means that one of these timers is still
735  * running. They are all cancelled below anyway by the
736  * call to CancelAllEvents (because of at least one
737  * of these two timers) which will trigger a call to the
738  * previous listener's cancel method.
739  *
740  * This typically happens because the high-priority
741  * QapScheduler has taken access to the channel from
742  * one of the Edca of the QAP.
743  */
744  m_currentPacket = packet->Copy ();
745  m_currentHdr = *hdr;
746  CancelAllEvents ();
747  m_listener = listener;
748  m_txParams = params;
750 
752  {
753  //This is mainly encountered when a higher priority control frame (such as beacons)
754  //is sent between A-MPDU transmissions. It avoids to unexpectedly flush the aggregate
755  //queue when previous RTS request has failed.
756  m_ampdu = false;
757  }
758  else if (m_aggregateQueue->GetSize () > 0)
759  {
760  //m_aggregateQueue > 0 occurs when a RTS/CTS exchange failed before an A-MPDU transmission.
761  //In that case, we transmit the same A-MPDU as previously.
762  m_sentMpdus = m_aggregateQueue->GetSize ();
763  m_ampdu = true;
764  if (m_sentMpdus > 1)
765  {
767  }
768  else if (m_currentHdr.IsQosData ())
769  {
770  //VHT single MPDUs are followed by normal ACKs
772  }
773  }
774  else
775  {
776  //Perform MPDU aggregation if possible
778  if (m_ampdu)
779  {
780  AmpduTag ampdu;
782  if (ampdu.GetNoOfMpdus () > 1)
783  {
785  }
786  else if (m_currentHdr.IsQosData ())
787  {
788  //VHT single MPDUs are followed by normal ACKs
790  }
791  }
792  }
793 
794  if (NeedRts ())
795  {
797  }
798  else
799  {
801  }
802 
803  NS_LOG_DEBUG ("startTx size=" << GetSize (m_currentPacket, &m_currentHdr) <<
804  ", to=" << m_currentHdr.GetAddr1 () << ", listener=" << m_listener);
805 
806  if (m_txParams.MustSendRts ())
807  {
808  SendRtsForPacket ();
809  }
810  else
811  {
813  {
814  SendCtsToSelf ();
815  }
816  else
817  {
818  SendDataPacket ();
819  }
820  }
821 
822  /* When this method completes, we have taken ownership of the medium. */
823  NS_ASSERT (m_phy->IsStateTx ());
824 }
825 
826 bool
828 {
831  m_currentPacket, dataTxVector);
832 }
833 
834 bool
836 {
838  return m_stationManager->NeedCtsToSelf (dataTxVector);
839 }
840 
841 void
842 MacLow::ReceiveError (Ptr<Packet> packet, double rxSnr, bool isEndOfFrame)
843 {
844  NS_LOG_FUNCTION (this << packet << rxSnr << isEndOfFrame);
845  NS_LOG_DEBUG ("rx failed ");
846  if (isEndOfFrame == true && m_receivedAtLeastOneMpdu == true)
847  {
848  WifiMacHeader hdr;
849  AmpduTag ampdu;
850  if (packet->RemovePacketTag (ampdu))
851  {
853  mpdu.begin ()->first->PeekHeader (hdr);
854  }
855  else
856  {
857  packet->PeekHeader (hdr);
858  }
859  if (hdr.GetAddr1 () != m_self)
860  {
861  NS_LOG_DEBUG ("hdr addr1 " << hdr.GetAddr1 () << "not for me (" << m_self << "); returning");
862  return;
863  }
865  NS_LOG_DEBUG ("last a-mpdu subframe detected/sendImmediateBlockAck from=" << m_lastReceivedHdr.GetAddr2 ());
872  rxSnr);
873  m_receivedAtLeastOneMpdu = false;
874  }
876  {
880  }
881  return;
882 }
883 
884 void
886 {
887  NS_LOG_DEBUG ("switching channel. Cancelling MAC pending events");
889  CancelAllEvents ();
891  {
893  }
896  m_currentPacket = 0;
897  m_listener = 0;
898 }
899 
900 void
902 {
903  NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
904  CancelAllEvents ();
906  {
908  }
911  m_currentPacket = 0;
912  m_listener = 0;
913 }
914 
915 void
916 MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, WifiPreamble preamble, bool ampduSubframe)
917 {
918  NS_LOG_FUNCTION (this << packet << rxSnr << txVector.GetMode () << preamble);
919  /* A packet is received from the PHY.
920  * When we have handled this packet,
921  * we handle any packet present in the
922  * packet queue.
923  */
924  WifiMacHeader hdr;
925  packet->RemoveHeader (hdr);
926  m_lastReceivedHdr = hdr;
927 
928  bool isPrevNavZero = IsNavZero ();
929  NS_LOG_DEBUG ("duration/id=" << hdr.GetDuration ());
930  NotifyNav (packet, hdr, preamble);
931  if (hdr.IsRts ())
932  {
933  /* see section 9.2.5.7 802.11-1999
934  * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS
935  * period if the NAV at the STA receiving the RTS frame indicates that the medium is
936  * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle,
937  * that STA shall not respond to the RTS frame.
938  */
939  if (ampduSubframe)
940  {
941  NS_FATAL_ERROR ("Received RTS as part of an A-MPDU");
942  }
943  else
944  {
945  if (isPrevNavZero
946  && hdr.GetAddr1 () == m_self)
947  {
948  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
950  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
951  rxSnr, txVector.GetMode ());
954  hdr.GetAddr2 (),
955  hdr.GetDuration (),
956  txVector,
957  rxSnr);
958  }
959  else
960  {
961  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
962  }
963  }
964  }
965  else if (hdr.IsCts ()
966  && hdr.GetAddr1 () == m_self
968  && m_currentPacket != 0)
969  {
970  if (ampduSubframe)
971  {
972  NS_FATAL_ERROR ("Received CTS as part of an A-MPDU");
973  }
974 
975  NS_LOG_DEBUG ("receive cts from=" << m_currentHdr.GetAddr1 ());
976 
977  SnrTag tag;
978  packet->RemovePacketTag (tag);
980  rxSnr, txVector.GetMode ());
982  rxSnr, txVector.GetMode (), tag.Get ());
983 
986  m_listener->GotCts (rxSnr, txVector.GetMode ());
990  hdr.GetAddr1 (),
991  hdr.GetDuration ());
992  }
993  else if (hdr.IsAck ()
994  && hdr.GetAddr1 () == m_self
998  && m_txParams.MustWaitAck ())
999  {
1000  NS_LOG_DEBUG ("receive ack from=" << m_currentHdr.GetAddr1 ());
1001  SnrTag tag;
1002  packet->RemovePacketTag (tag);
1004  rxSnr, txVector.GetMode ());
1006  rxSnr, txVector.GetMode (), tag.Get ());
1007 
1009  m_ampdu = false;
1010  bool gotAck = false;
1011 
1014  {
1017  gotAck = true;
1018  }
1021  {
1024  gotAck = true;
1025  }
1026  if (gotAck)
1027  {
1028  m_listener->GotAck (rxSnr, txVector.GetMode ());
1029  }
1030  if (m_txParams.HasNextPacket ())
1031  {
1034  }
1035  }
1036  else if (hdr.IsBlockAck () && hdr.GetAddr1 () == m_self
1039  {
1040  NS_LOG_DEBUG ("got block ack from " << hdr.GetAddr2 ());
1041  SnrTag tag;
1042  packet->RemovePacketTag (tag);
1043  CtrlBAckResponseHeader blockAck;
1044  packet->RemoveHeader (blockAck);
1047  m_listener->GotBlockAck (&blockAck, hdr.GetAddr2 (), rxSnr, txVector.GetMode (), tag.Get ());
1048  m_sentMpdus = 0;
1049  m_ampdu = false;
1051  }
1052  else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
1053  {
1054  CtrlBAckRequestHeader blockAckReq;
1055  packet->RemoveHeader (blockAckReq);
1056  if (!blockAckReq.IsMultiTid ())
1057  {
1058  uint8_t tid = blockAckReq.GetTidInfo ();
1059  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), tid));
1060  if (it != m_bAckAgreements.end ())
1061  {
1062  //Update block ack cache
1063  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), tid));
1064  NS_ASSERT (i != m_bAckCaches.end ());
1065  (*i).second.UpdateWithBlockAckReq (blockAckReq.GetStartingSequence ());
1066 
1068  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
1069  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
1070  if ((*it).second.first.IsImmediateBlockAck ())
1071  {
1072  NS_LOG_DEBUG ("rx blockAckRequest/sendImmediateBlockAck from=" << hdr.GetAddr2 ());
1075  blockAckReq,
1076  hdr.GetAddr2 (),
1077  hdr.GetDuration (),
1078  txVector.GetMode (),
1079  rxSnr);
1080  }
1081  else
1082  {
1083  NS_FATAL_ERROR ("Delayed block ack not supported.");
1084  }
1085  m_receivedAtLeastOneMpdu = false;
1086  }
1087  else
1088  {
1089  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
1090  }
1091  }
1092  else
1093  {
1094  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
1095  }
1096  }
1097  else if (hdr.IsCtl ())
1098  {
1099  NS_LOG_DEBUG ("rx drop " << hdr.GetTypeString ());
1100  m_receivedAtLeastOneMpdu = false;
1101  }
1102  else if (hdr.GetAddr1 () == m_self)
1103  {
1104  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
1105  rxSnr, txVector.GetMode ());
1106  if (hdr.IsQosData () && ReceiveMpdu (packet, hdr))
1107  {
1108  /* From section 9.10.4 in IEEE 802.11:
1109  Upon the receipt of a QoS data frame from the originator for which
1110  the Block Ack agreement exists, the recipient shall buffer the MSDU
1111  regardless of the value of the Ack Policy subfield within the
1112  QoS Control field of the QoS data frame. */
1113  if (hdr.IsQosAck () && !ampduSubframe)
1114  {
1115  NS_LOG_DEBUG ("rx QoS unicast/sendAck from=" << hdr.GetAddr2 ());
1116  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1117 
1118  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (),
1119  hdr.GetAddr2 (), hdr.GetQosTid ());
1120  RxCompleteBufferedPacketsUntilFirstLost (hdr.GetAddr2 (), hdr.GetQosTid ());
1123  &MacLow::SendAckAfterData, this,
1124  hdr.GetAddr2 (),
1125  hdr.GetDuration (),
1126  txVector.GetMode (),
1127  rxSnr);
1128  m_receivedAtLeastOneMpdu = false;
1129  }
1130  else if (hdr.IsQosBlockAck ())
1131  {
1132  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1133  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
1134  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
1135  }
1136  return;
1137  }
1138  else if (hdr.IsQosData () && hdr.IsQosBlockAck ())
1139  {
1140  /* This happens if a packet with ack policy Block Ack is received and a block ack
1141  agreement for that packet doesn't exist.
1142 
1143  From section 11.5.3 in IEEE 802.11e:
1144  When a recipient does not have an active Block ack for a TID, but receives
1145  data MPDUs with the Ack Policy subfield set to Block Ack, it shall discard
1146  them and shall send a DELBA frame using the normal access
1147  mechanisms. */
1148  AcIndex ac = QosUtilsMapTidToAc (hdr.GetQosTid ());
1149  m_edcaListeners[ac]->BlockAckInactivityTimeout (hdr.GetAddr2 (), hdr.GetQosTid ());
1150  return;
1151  }
1152  else if (hdr.IsQosData () && hdr.IsQosNoAck ())
1153  {
1154  if (ampduSubframe)
1155  {
1156  NS_LOG_DEBUG ("rx Ampdu with No Ack Policy from=" << hdr.GetAddr2 ());
1157  }
1158  else
1159  {
1160  NS_LOG_DEBUG ("rx unicast/noAck from=" << hdr.GetAddr2 ());
1161  }
1162  }
1163  else if (hdr.IsData () || hdr.IsMgt ())
1164  {
1165  if (hdr.IsMgt () && ampduSubframe)
1166  {
1167  NS_FATAL_ERROR ("Received management packet as part of an A-MPDU");
1168  }
1169  else
1170  {
1171  NS_LOG_DEBUG ("rx unicast/sendAck from=" << hdr.GetAddr2 ());
1174  &MacLow::SendAckAfterData, this,
1175  hdr.GetAddr2 (),
1176  hdr.GetDuration (),
1177  txVector.GetMode (),
1178  rxSnr);
1179  m_receivedAtLeastOneMpdu = false;
1180  }
1181  }
1182  goto rxPacket;
1183  }
1184  else if (hdr.GetAddr1 ().IsGroup ())
1185  {
1186  if (ampduSubframe)
1187  {
1188  NS_FATAL_ERROR ("Received group addressed packet as part of an A-MPDU");
1189  }
1190  else
1191  {
1192  if (hdr.IsData () || hdr.IsMgt ())
1193  {
1194  NS_LOG_DEBUG ("rx group from=" << hdr.GetAddr2 ());
1195  m_receivedAtLeastOneMpdu = false;
1196  goto rxPacket;
1197  }
1198  else
1199  {
1200  // DROP
1201  }
1202  }
1203  }
1204  else if (m_promisc)
1205  {
1206  NS_ASSERT (hdr.GetAddr1 () != m_self);
1207  if (hdr.IsData ())
1208  {
1209  goto rxPacket;
1210  }
1211  }
1212  else
1213  {
1214  //NS_LOG_DEBUG_VERBOSE ("rx not-for-me from %d", GetSource (packet));
1215  }
1216  return;
1217 rxPacket:
1218  WifiMacTrailer fcs;
1219  packet->RemoveTrailer (fcs);
1220  m_rxCallback (packet, &hdr);
1221  return;
1222 }
1223 
1224 uint8_t
1226 {
1227  uint8_t tid = 0;
1228  if (hdr.IsQosData ())
1229  {
1230  tid = hdr.GetQosTid ();
1231  }
1232  else if (hdr.IsBlockAckReq ())
1233  {
1234  CtrlBAckRequestHeader baReqHdr;
1235  packet->PeekHeader (baReqHdr);
1236  tid = baReqHdr.GetTidInfo ();
1237  }
1238  else if (hdr.IsBlockAck ())
1239  {
1240  CtrlBAckResponseHeader baRespHdr;
1241  packet->PeekHeader (baRespHdr);
1242  tid = baRespHdr.GetTidInfo ();
1243  }
1244  return tid;
1245 }
1246 
1247 uint32_t
1249 {
1250  WifiMacHeader ack;
1251  ack.SetType (WIFI_MAC_CTL_ACK);
1252  return ack.GetSize () + 4;
1253 }
1254 
1255 uint32_t
1257 {
1258  WifiMacHeader hdr;
1260  CtrlBAckResponseHeader blockAck;
1261  if (type == BASIC_BLOCK_ACK)
1262  {
1263  blockAck.SetType (BASIC_BLOCK_ACK);
1264  }
1265  else if (type == COMPRESSED_BLOCK_ACK)
1266  {
1267  blockAck.SetType (COMPRESSED_BLOCK_ACK);
1268  }
1269  else if (type == MULTI_TID_BLOCK_ACK)
1270  {
1271  //Not implemented
1272  NS_ASSERT (false);
1273  }
1274  return hdr.GetSize () + blockAck.GetSerializedSize () + 4;
1275 }
1276 
1277 uint32_t
1279 {
1280  WifiMacHeader rts;
1281  rts.SetType (WIFI_MAC_CTL_RTS);
1282  return rts.GetSize () + 4;
1283 }
1284 
1285 Time
1287 {
1288  WifiTxVector ackTxVector = GetAckTxVectorForData (to, dataTxVector.GetMode ());
1289  return GetAckDuration (ackTxVector);
1290 }
1291 
1292 Time
1294 {
1295  NS_ASSERT (ackTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
1296  WifiPreamble preamble;
1298  {
1299  preamble = WIFI_PREAMBLE_SHORT;
1300  }
1301  else
1302  {
1303  preamble = WIFI_PREAMBLE_LONG;
1304  }
1305  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, preamble, m_phy->GetFrequency ());
1306 }
1307 
1308 Time
1309 MacLow::GetBlockAckDuration (Mac48Address to, WifiTxVector blockAckReqTxVector, enum BlockAckType type) const
1310 {
1311  /*
1312  * For immediate Basic BlockAck we should transmit the frame with the same WifiMode
1313  * as the BlockAckReq.
1314  */
1315  WifiPreamble preamble;
1316  if (blockAckReqTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT && type == BASIC_BLOCK_ACK)
1317  {
1318  preamble = WIFI_PREAMBLE_HT_MF;
1319  }
1321  {
1322  preamble = WIFI_PREAMBLE_SHORT;
1323  }
1324  else
1325  {
1326  preamble = WIFI_PREAMBLE_LONG;
1327  }
1328  return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, preamble, m_phy->GetFrequency ());
1329 }
1330 
1331 Time
1333 {
1334  WifiTxVector ctsTxVector = GetCtsTxVectorForRts (to, rtsTxVector.GetMode ());
1335  return GetCtsDuration (ctsTxVector);
1336 }
1337 
1338 Time
1340 {
1341  NS_ASSERT (ctsTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1342  WifiPreamble preamble;
1344  {
1345  preamble = WIFI_PREAMBLE_SHORT;
1346  }
1347  else
1348  {
1349  preamble = WIFI_PREAMBLE_LONG;
1350  }
1351  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency ());
1352 }
1353 
1354 uint32_t
1356 {
1357  WifiMacHeader cts;
1358  cts.SetType (WIFI_MAC_CTL_CTS);
1359  return cts.GetSize () + 4;
1360 }
1361 
1362 uint32_t
1364 {
1365  uint32_t size;
1366  WifiMacTrailer fcs;
1367  if (m_ampdu)
1368  {
1369  size = packet->GetSize ();
1370  }
1371  else
1372  {
1373  size = packet->GetSize () + hdr->GetSize () + fcs.GetSerializedSize ();
1374  }
1375  return size;
1376 }
1377 
1380 {
1381  return m_stationManager->GetCtsToSelfTxVector (hdr, packet);
1382 }
1383 
1386 {
1387  Mac48Address to = hdr->GetAddr1 ();
1388  return m_stationManager->GetRtsTxVector (to, hdr, packet);
1389 }
1390 
1393 {
1394  Mac48Address to = hdr->GetAddr1 ();
1395  WifiMacTrailer fcs;
1396  return m_stationManager->GetDataTxVector (to, hdr, packet);
1397 }
1398 
1401 {
1402  return m_stationManager->GetCtsTxVector (to, rtsTxMode);
1403 }
1404 
1407 {
1408  return m_stationManager->GetAckTxVector (to, dataTxMode);
1409 }
1410 
1413 {
1414  return m_stationManager->GetBlockAckTxVector (to, dataTxMode);
1415 }
1416 
1419 {
1420  return GetCtsTxVector (to, rtsTxMode);
1421 }
1422 
1425 {
1426  return GetAckTxVector (to, dataTxMode);
1427 }
1428 
1429 Time
1431  const WifiMacHeader* hdr,
1432  const MacLowTransmissionParameters& params) const
1433 {
1434  WifiPreamble preamble;
1435  Time txTime = Seconds (0);
1436  if (params.MustSendRts ())
1437  {
1438  WifiTxVector rtsTxVector = GetRtsTxVector (packet, hdr);
1439  //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
1441  {
1442  preamble = WIFI_PREAMBLE_HT_GF;
1443  }
1444  //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1446  {
1447  preamble = WIFI_PREAMBLE_SHORT;
1448  }
1449  else
1450  {
1451  preamble = WIFI_PREAMBLE_LONG;
1452  }
1453  txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency ());
1454  txTime += GetCtsDuration (hdr->GetAddr1 (), rtsTxVector);
1455  txTime += Time (GetSifs () * 2);
1456  }
1457  WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
1458  if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_VHT)
1459  {
1460  preamble = WIFI_PREAMBLE_VHT;
1461  }
1463  {
1464  preamble = WIFI_PREAMBLE_HT_GF;
1465  }
1466  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1467  {
1468  preamble = WIFI_PREAMBLE_HT_MF;
1469  }
1471  {
1472  preamble = WIFI_PREAMBLE_SHORT;
1473  }
1474  else
1475  {
1476  preamble = WIFI_PREAMBLE_LONG;
1477  }
1478  uint32_t dataSize = GetSize (packet, hdr);
1479  txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, preamble, m_phy->GetFrequency ());
1480  if (params.MustWaitAck ())
1481  {
1482  txTime += GetSifs ();
1483  txTime += GetAckDuration (hdr->GetAddr1 (), dataTxVector);
1484  }
1485  return txTime;
1486 }
1487 
1488 Time
1490  const WifiMacHeader* hdr,
1491  const MacLowTransmissionParameters& params) const
1492 {
1493  Time txTime = CalculateOverallTxTime (packet, hdr, params);
1494  if (params.HasNextPacket ())
1495  {
1496  WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
1497  WifiPreamble preamble;
1498  if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1499  {
1500  preamble = WIFI_PREAMBLE_VHT;
1501  }
1503  {
1504  preamble = WIFI_PREAMBLE_HT_GF;
1505  }
1506  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1507  {
1508  preamble = WIFI_PREAMBLE_HT_MF;
1509  }
1511  {
1512  preamble = WIFI_PREAMBLE_SHORT;
1513  }
1514  else
1515  {
1516  preamble = WIFI_PREAMBLE_LONG;
1517  }
1518  txTime += GetSifs ();
1519  txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, preamble, m_phy->GetFrequency ());
1520  }
1521  return txTime;
1522 }
1523 
1524 void
1526 {
1528  Time duration = hdr.GetDuration ();
1529 
1530  if (hdr.IsCfpoll ()
1531  && hdr.GetAddr2 () == m_bssid)
1532  {
1533  //see section 9.3.2.2 802.11-1999
1534  DoNavResetNow (duration);
1535  return;
1536  }
1539  else if (hdr.GetAddr1 () != m_self)
1540  {
1541  // see section 9.2.5.4 802.11-1999
1542  bool navUpdated = DoNavStartNow (duration);
1543  if (hdr.IsRts () && navUpdated)
1544  {
1553  WifiMacHeader cts;
1554  cts.SetType (WIFI_MAC_CTL_CTS);
1555  WifiTxVector txVector = GetRtsTxVector (packet, &hdr);
1556  Time navCounterResetCtsMissedDelay =
1557  m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, preamble, m_phy->GetFrequency ()) +
1558  Time (2 * GetSifs ()) + Time (2 * GetSlotTime ());
1559  m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
1561  Simulator::Now ());
1562  }
1563  }
1564 }
1565 
1566 void
1568 {
1569  if (m_phy->GetLastRxStartTime () < rtsEndRxTime)
1570  {
1571  DoNavResetNow (Seconds (0.0));
1572  }
1573 }
1574 
1575 void
1577 {
1578  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1579  {
1580  (*i)->NavReset (duration);
1581  }
1583  m_lastNavDuration = duration;
1584 }
1585 
1586 bool
1588 {
1589  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1590  {
1591  (*i)->NavStart (duration);
1592  }
1593  Time newNavEnd = Simulator::Now () + duration;
1594  Time oldNavEnd = m_lastNavStart + m_lastNavDuration;
1595  if (newNavEnd > oldNavEnd)
1596  {
1598  m_lastNavDuration = duration;
1599  return true;
1600  }
1601  return false;
1602 }
1603 
1604 void
1606 {
1607  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1608  {
1609  (*i)->AckTimeoutStart (duration);
1610  }
1611 }
1612 
1613 void
1615 {
1616  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1617  {
1618  (*i)->AckTimeoutReset ();
1619  }
1620 }
1621 
1622 void
1624 {
1625  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1626  {
1627  (*i)->CtsTimeoutStart (duration);
1628  }
1629 }
1630 
1631 void
1633 {
1634  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1635  {
1636  (*i)->CtsTimeoutReset ();
1637  }
1638 }
1639 
1640 void
1642  WifiTxVector txVector, WifiPreamble preamble)
1643 {
1644  NS_LOG_FUNCTION (this << packet << hdr << txVector);
1645  NS_LOG_DEBUG ("send " << hdr->GetTypeString () <<
1646  ", to=" << hdr->GetAddr1 () <<
1647  ", size=" << packet->GetSize () <<
1648  ", mode=" << txVector.GetMode () <<
1649  ", duration=" << hdr->GetDuration () <<
1650  ", seq=0x" << std::hex << m_currentHdr.GetSequenceControl () << std::dec);
1651  if (!m_ampdu || hdr->IsRts () || hdr->IsBlockAck ())
1652  {
1653  m_phy->SendPacket (packet, txVector, preamble);
1654  }
1655  else
1656  {
1657  Ptr<Packet> newPacket;
1658  Ptr <const Packet> dequeuedPacket;
1659  WifiMacHeader newHdr;
1660  WifiMacTrailer fcs;
1661  m_nTxMpdus = m_aggregateQueue->GetSize ();
1662  uint32_t queueSize = m_aggregateQueue->GetSize ();
1663  bool vhtSingleMpdu = false;
1664  bool last = false;
1665  enum mpduType mpdutype = NORMAL_MPDU;
1666 
1667  uint8_t tid = GetTid (packet, *hdr);
1668  AcIndex ac = QosUtilsMapTidToAc (tid);
1669  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt = m_edcaListeners.find (ac);
1670 
1671  if (queueSize == 1)
1672  {
1673  vhtSingleMpdu = true;
1674  }
1675 
1676  //Add packet tag
1677  AmpduTag ampdutag;
1678  ampdutag.SetAmpdu (true);
1679  Time delay = Seconds (0);
1680  if (queueSize > 1 || vhtSingleMpdu)
1681  {
1682  txVector.SetAggregation (true);
1683  }
1684  for (; queueSize > 0; queueSize--)
1685  {
1686  dequeuedPacket = m_aggregateQueue->Dequeue (&newHdr);
1687  newPacket = dequeuedPacket->Copy ();
1688  newHdr.SetDuration (hdr->GetDuration ());
1689  newPacket->AddHeader (newHdr);
1690  newPacket->AddTrailer (fcs);
1691  if (queueSize == 1)
1692  {
1693  last = true;
1694  mpdutype = LAST_MPDU_IN_AGGREGATE;
1695  }
1696 
1697  listenerIt->second->GetMpduAggregator ()->AddHeaderAndPad (newPacket, last, vhtSingleMpdu);
1698 
1699  ampdutag.SetNoOfMpdus (queueSize);
1700  newPacket->AddPacketTag (ampdutag);
1701 
1702  if (delay == Seconds (0))
1703  {
1704  if (!vhtSingleMpdu)
1705  {
1706  NS_LOG_DEBUG ("Sending MPDU as part of A-MPDU");
1707  mpdutype = MPDU_IN_AGGREGATE;
1708  }
1709  else
1710  {
1711  mpdutype = NORMAL_MPDU;
1712  }
1713  m_phy->SendPacket (newPacket, txVector, preamble, mpdutype);
1714  }
1715  else
1716  {
1717  Simulator::Schedule (delay, &MacLow::SendMpdu, this, newPacket, txVector, preamble, mpdutype);
1718  }
1719  if (queueSize > 1)
1720  {
1721  delay = delay + m_phy->CalculateTxDuration (GetSize (newPacket, &newHdr), txVector, preamble, m_phy->GetFrequency (), mpdutype, 0);
1722  }
1723  preamble = WIFI_PREAMBLE_NONE;
1724  }
1725  }
1726 }
1727 
1728 void
1729 MacLow::SendMpdu (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, enum mpduType mpdutype)
1730 {
1731  NS_LOG_DEBUG ("Sending MPDU as part of A-MPDU");
1732  m_phy->SendPacket (packet, txVector, preamble, mpdutype);
1733 }
1734 
1735 void
1737 {
1738  NS_LOG_FUNCTION (this);
1739  NS_LOG_DEBUG ("cts timeout");
1744  if (m_sentMpdus == 0)
1745  {
1746  m_currentPacket = 0;
1747  }
1749  m_listener = 0;
1750  m_sentMpdus = 0;
1751  m_ampdu = false;
1752  listener->MissedCts ();
1753 }
1754 
1755 void
1757 {
1758  NS_LOG_FUNCTION (this);
1759  NS_LOG_DEBUG ("normal ack timeout");
1765  m_listener = 0;
1766  m_sentMpdus = 0;
1767  m_ampdu = false;
1769  listener->MissedAck ();
1770 }
1771 
1772 void
1774 {
1775  NS_LOG_FUNCTION (this);
1778  m_listener = 0;
1779  if (m_phy->IsStateIdle ())
1780  {
1781  NS_LOG_DEBUG ("fast Ack idle missed");
1782  listener->MissedAck ();
1783  }
1784  else
1785  {
1786  NS_LOG_DEBUG ("fast Ack ok");
1787  }
1788 }
1789 
1790 void
1792 {
1793  NS_LOG_FUNCTION (this);
1794  NS_LOG_DEBUG ("block ack timeout");
1796  m_listener = 0;
1797  m_sentMpdus = 0;
1798  m_ampdu = false;
1800  listener->MissedBlockAck (m_nTxMpdus);
1801 }
1802 
1803 void
1805 {
1806  NS_LOG_FUNCTION (this);
1809  m_listener = 0;
1810  if (m_phy->IsStateIdle ())
1811  {
1812  NS_LOG_DEBUG ("super fast Ack failed");
1813  listener->MissedAck ();
1814  }
1815  else
1816  {
1817  NS_LOG_DEBUG ("super fast Ack ok");
1818  listener->GotAck (0.0, WifiMode ());
1819  }
1820 }
1821 
1822 void
1824 {
1825  NS_LOG_FUNCTION (this);
1826  /* send an RTS for this packet. */
1827  WifiMacHeader rts;
1828  rts.SetType (WIFI_MAC_CTL_RTS);
1829  rts.SetDsNotFrom ();
1830  rts.SetDsNotTo ();
1831  rts.SetNoRetry ();
1832  rts.SetNoMoreFragments ();
1833  rts.SetAddr1 (m_currentHdr.GetAddr1 ());
1834  rts.SetAddr2 (m_self);
1836  Time duration = Seconds (0);
1837 
1838  WifiPreamble preamble;
1839  //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
1841  {
1842  preamble = WIFI_PREAMBLE_HT_GF;
1843  }
1844  //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1846  {
1847  preamble = WIFI_PREAMBLE_SHORT;
1848  }
1849  else
1850  {
1851  preamble = WIFI_PREAMBLE_LONG;
1852  }
1853 
1854  if (m_txParams.HasDurationId ())
1855  {
1856  duration += m_txParams.GetDurationId ();
1857  }
1858  else
1859  {
1860  duration += GetSifs ();
1861  duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxVector);
1862  duration += GetSifs ();
1864  m_currentTxVector, preamble, m_phy->GetFrequency ());
1865  duration += GetSifs ();
1867  {
1869  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
1870  }
1872  {
1874  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1875  }
1876  else if (m_txParams.MustWaitAck ())
1877  {
1879  }
1880  if (m_txParams.HasNextPacket ())
1881  {
1883  m_currentTxVector, preamble, m_phy->GetFrequency ());
1884  if (m_txParams.MustWaitAck ())
1885  {
1886  duration += GetSifs ();
1888  }
1889  }
1890  }
1891  rts.SetDuration (duration);
1892 
1893  Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency ());
1894  Time timerDelay = txDuration + GetCtsTimeout ();
1895 
1897  NotifyCtsTimeoutStartNow (timerDelay);
1899 
1900  Ptr<Packet> packet = Create<Packet> ();
1901  packet->AddHeader (rts);
1902  WifiMacTrailer fcs;
1903  packet->AddTrailer (fcs);
1904 
1905  ForwardDown (packet, &rts, rtsTxVector, preamble);
1906 }
1907 
1908 void
1910 {
1911  WifiPreamble preamble;
1912 
1913  if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_VHT)
1914  {
1915  preamble = WIFI_PREAMBLE_VHT;
1916  }
1917  //Since it is data then it can have format = GF
1919  {
1920  preamble = WIFI_PREAMBLE_HT_GF;
1921  }
1922  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1923  {
1924  preamble = WIFI_PREAMBLE_HT_MF;
1925  }
1927  {
1928  preamble = WIFI_PREAMBLE_SHORT;
1929  }
1930  else
1931  {
1932  preamble = WIFI_PREAMBLE_LONG;
1933  }
1934 
1935  Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), dataTxVector, preamble, m_phy->GetFrequency ());
1937  {
1938  Time timerDelay = txDuration + GetAckTimeout ();
1940  NotifyAckTimeoutStartNow (timerDelay);
1942  }
1943  else if (m_txParams.MustWaitFastAck ())
1944  {
1945  Time timerDelay = txDuration + GetPifs ();
1947  NotifyAckTimeoutStartNow (timerDelay);
1949  }
1950  else if (m_txParams.MustWaitSuperFastAck ())
1951  {
1952  Time timerDelay = txDuration + GetPifs ();
1954  NotifyAckTimeoutStartNow (timerDelay);
1957  }
1958  else if (m_txParams.MustWaitBasicBlockAck ())
1959  {
1960  Time timerDelay = txDuration + GetBasicBlockAckTimeout ();
1962  NotifyAckTimeoutStartNow (timerDelay);
1964  }
1966  {
1967  Time timerDelay = txDuration + GetCompressedBlockAckTimeout ();
1969  NotifyAckTimeoutStartNow (timerDelay);
1971  }
1972  else if (m_txParams.HasNextPacket ())
1973  {
1975  {
1976  Time delay = txDuration + GetRifs ();
1979  }
1980  else
1981  {
1982  Time delay = txDuration + GetSifs ();
1985  }
1986  }
1987  else
1988  {
1989  // since we do not expect any timer to be triggered.
1990  Simulator::Schedule (txDuration, &MacLow::EndTxNoAck, this);
1991  }
1992 }
1993 
1994 void
1996 {
1997  NS_LOG_FUNCTION (this);
1998  /* send this packet directly. No RTS is needed. */
1999  WifiPreamble preamble;
2001  {
2002  preamble = WIFI_PREAMBLE_VHT;
2003  }
2005  {
2006  //In the future has to make sure that receiver has greenfield enabled
2007  preamble = WIFI_PREAMBLE_HT_GF;
2008  }
2010  {
2011  preamble = WIFI_PREAMBLE_HT_MF;
2012  }
2014  {
2015  preamble = WIFI_PREAMBLE_SHORT;
2016  }
2017  else
2018  {
2019  preamble = WIFI_PREAMBLE_LONG;
2020  }
2021 
2023 
2024  Time duration = Seconds (0.0);
2025  if (m_txParams.HasDurationId ())
2026  {
2027  duration += m_txParams.GetDurationId ();
2028  }
2029  else
2030  {
2032  {
2033  duration += GetSifs ();
2035  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
2036  }
2038  {
2039  duration += GetSifs ();
2041  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2042  }
2043  else if (m_txParams.MustWaitAck ())
2044  {
2045  duration += GetSifs ();
2047  }
2048  if (m_txParams.HasNextPacket ())
2049  {
2050  duration += GetSifs ();
2052  m_currentTxVector, preamble, m_phy->GetFrequency ());
2053  if (m_txParams.MustWaitAck ())
2054  {
2055  duration += GetSifs ();
2057  }
2058  }
2059  }
2060  m_currentHdr.SetDuration (duration);
2061 
2062  if (!m_ampdu)
2063  {
2065  WifiMacTrailer fcs;
2066  m_currentPacket->AddTrailer (fcs);
2067  }
2068 
2070  m_currentPacket = 0;
2071 }
2072 
2073 bool
2074 MacLow::IsNavZero (void) const
2075 {
2077  {
2078  return true;
2079  }
2080  else
2081  {
2082  return false;
2083  }
2084 }
2085 
2086 void
2088 {
2089  WifiMacHeader cts;
2090  cts.SetType (WIFI_MAC_CTL_CTS);
2091  cts.SetDsNotFrom ();
2092  cts.SetDsNotTo ();
2093  cts.SetNoMoreFragments ();
2094  cts.SetNoRetry ();
2095  cts.SetAddr1 (m_self);
2096 
2098 
2099  WifiPreamble preamble;
2100  if (ctsTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
2101  {
2102  preamble = WIFI_PREAMBLE_HT_MF;
2103  }
2105  {
2106  preamble = WIFI_PREAMBLE_SHORT;
2107  }
2108  else
2109  {
2110  preamble = WIFI_PREAMBLE_LONG;
2111  }
2112 
2113  Time duration = Seconds (0);
2114 
2115  if (m_txParams.HasDurationId ())
2116  {
2117  duration += m_txParams.GetDurationId ();
2118  }
2119  else
2120  {
2121  duration += GetSifs ();
2123  m_currentTxVector, preamble, m_phy->GetFrequency ());
2125  {
2126 
2127  duration += GetSifs ();
2129  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
2130  }
2132  {
2133  duration += GetSifs ();
2135  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2136  }
2137  else if (m_txParams.MustWaitAck ())
2138  {
2139  duration += GetSifs ();
2141  }
2142  if (m_txParams.HasNextPacket ())
2143  {
2144  duration += GetSifs ();
2146  m_currentTxVector, preamble, m_phy->GetFrequency ());
2148  {
2149  duration += GetSifs ();
2151  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2152  }
2153  else if (m_txParams.MustWaitAck ())
2154  {
2155  duration += GetSifs ();
2157  }
2158  }
2159  }
2160 
2161  cts.SetDuration (duration);
2162 
2163  Ptr<Packet> packet = Create<Packet> ();
2164  packet->AddHeader (cts);
2165  WifiMacTrailer fcs;
2166  packet->AddTrailer (fcs);
2167 
2168  ForwardDown (packet, &cts, ctsTxVector,preamble);
2169 
2170  Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency ());
2171  txDuration += GetSifs ();
2173 
2174  m_sendDataEvent = Simulator::Schedule (txDuration,
2175  &MacLow::SendDataAfterCts, this,
2176  cts.GetAddr1 (),
2177  duration);
2178 
2179 }
2180 
2181 void
2182 MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
2183 {
2184  NS_LOG_FUNCTION (this << source << duration << rtsTxVector.GetMode () << rtsSnr);
2185  /* send a CTS when you receive a RTS
2186  * right after SIFS.
2187  */
2188  WifiTxVector ctsTxVector = GetCtsTxVector (source, rtsTxVector.GetMode ());
2189  WifiMacHeader cts;
2190  cts.SetType (WIFI_MAC_CTL_CTS);
2191  cts.SetDsNotFrom ();
2192  cts.SetDsNotTo ();
2193  cts.SetNoMoreFragments ();
2194  cts.SetNoRetry ();
2195  cts.SetAddr1 (source);
2196  duration -= GetCtsDuration (source, rtsTxVector);
2197  duration -= GetSifs ();
2198  NS_ASSERT (duration >= MicroSeconds (0));
2199  cts.SetDuration (duration);
2200 
2201  Ptr<Packet> packet = Create<Packet> ();
2202  packet->AddHeader (cts);
2203  WifiMacTrailer fcs;
2204  packet->AddTrailer (fcs);
2205 
2206  SnrTag tag;
2207  tag.Set (rtsSnr);
2208  packet->AddPacketTag (tag);
2209 
2210  WifiPreamble preamble;
2212  {
2213  preamble = WIFI_PREAMBLE_SHORT;
2214  }
2215  else
2216  {
2217  preamble = WIFI_PREAMBLE_LONG;
2218  }
2219 
2220  //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
2221  ForwardDown (packet, &cts, ctsTxVector, preamble);
2222 }
2223 
2224 void
2226 {
2227  NS_LOG_FUNCTION (this);
2228  /* send the third step in a
2229  * RTS/CTS/DATA/ACK hanshake
2230  */
2231  NS_ASSERT (m_currentPacket != 0);
2232 
2233  if (m_aggregateQueue->GetSize () != 0)
2234  {
2235  for (std::vector<Item>::size_type i = 0; i != m_txPackets.size (); i++)
2236  {
2237  uint8_t tid = GetTid (m_txPackets.at (i).packet, m_txPackets.at (i).hdr);
2238  AcIndex ac = QosUtilsMapTidToAc (tid);
2239  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt = m_edcaListeners.find (ac);
2240 
2241  listenerIt->second->CompleteMpduTx (m_txPackets.at (i).packet, m_txPackets.at (i).hdr, m_txPackets.at (i).timestamp);
2242  }
2243  m_txPackets.clear ();
2244  }
2245 
2246  WifiPreamble preamble;
2248  {
2249  preamble = WIFI_PREAMBLE_VHT;
2250  }
2252  {
2253  //In the future has to make sure that receiver has greenfield enabled
2254  preamble = WIFI_PREAMBLE_HT_GF;
2255  }
2257  {
2258  preamble = WIFI_PREAMBLE_HT_MF;
2259  }
2261  {
2262  preamble = WIFI_PREAMBLE_SHORT;
2263  }
2264  else
2265  {
2266  preamble = WIFI_PREAMBLE_LONG;
2267  }
2268 
2270  Time newDuration = Seconds (0);
2272  {
2273  newDuration += GetSifs ();
2275  newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
2276  }
2278  {
2279  newDuration += GetSifs ();
2281  newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2282  }
2283  else if (m_txParams.MustWaitAck ())
2284  {
2285  newDuration += GetSifs ();
2287  }
2288  if (m_txParams.HasNextPacket ())
2289  {
2290  newDuration += GetSifs ();
2293  {
2294  newDuration += GetSifs ();
2296  newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2297  }
2298  else if (m_txParams.MustWaitAck ())
2299  {
2300  newDuration += GetSifs ();
2302  }
2303  }
2304 
2306  duration -= txDuration;
2307  duration -= GetSifs ();
2308 
2309  duration = std::max (duration, newDuration);
2310  NS_ASSERT (duration >= MicroSeconds (0));
2311  m_currentHdr.SetDuration (duration);
2312 
2313  if (!m_ampdu)
2314  {
2316  WifiMacTrailer fcs;
2317  m_currentPacket->AddTrailer (fcs);
2318  }
2319 
2321  m_currentPacket = 0;
2322 }
2323 
2324 void
2326 {
2327  m_listener->StartNext ();
2328 }
2329 
2330 void
2332 {
2334  m_listener = 0;
2335  listener->EndTxNoAck ();
2336 }
2337 
2338 void
2340 {
2341  NS_LOG_FUNCTION (this);
2343  m_listener = 0;
2344  listener->MissedAck ();
2345  NS_LOG_DEBUG ("fast Ack busy but missed");
2346 }
2347 
2348 void
2349 MacLow::SendAckAfterData (Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
2350 {
2351  NS_LOG_FUNCTION (this);
2352  // send an ACK, after SIFS, when you receive a packet
2353  WifiTxVector ackTxVector = GetAckTxVector (source, dataTxMode);
2354  WifiMacHeader ack;
2355  ack.SetType (WIFI_MAC_CTL_ACK);
2356  ack.SetDsNotFrom ();
2357  ack.SetDsNotTo ();
2358  ack.SetNoRetry ();
2359  ack.SetNoMoreFragments ();
2360  ack.SetAddr1 (source);
2361  // 802.11-2012, Section 8.3.1.4: Duration/ID is received duration value
2362  // minus the time to transmit the ACK frame and its SIFS interval
2363  duration -= GetAckDuration (ackTxVector);
2364  duration -= GetSifs ();
2365  NS_ASSERT_MSG (duration >= MicroSeconds (0), "Please provide test case to maintainers if this assert is hit.");
2366  ack.SetDuration (duration);
2367 
2368  Ptr<Packet> packet = Create<Packet> ();
2369  packet->AddHeader (ack);
2370  WifiMacTrailer fcs;
2371  packet->AddTrailer (fcs);
2372 
2373  SnrTag tag;
2374  tag.Set (dataSnr);
2375  packet->AddPacketTag (tag);
2376 
2377  WifiPreamble preamble;
2379  {
2380  preamble = WIFI_PREAMBLE_SHORT;
2381  }
2382  else
2383  {
2384  preamble = WIFI_PREAMBLE_LONG;
2385  }
2386 
2387  //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
2388  ForwardDown (packet, &ack, ackTxVector, preamble);
2389 }
2390 
2391 bool
2392 MacLow::IsInWindow (uint16_t seq, uint16_t winstart, uint16_t winsize)
2393 {
2394  return ((seq - winstart + 4096) % 4096) < winsize;
2395 }
2396 
2397 bool
2399 {
2401  {
2402  Mac48Address originator = hdr.GetAddr2 ();
2403  uint8_t tid = 0;
2404  if (hdr.IsQosData ())
2405  {
2406  tid = hdr.GetQosTid ();
2407  }
2408  uint16_t seqNumber = hdr.GetSequenceNumber ();
2409  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2410  if (it != m_bAckAgreements.end ())
2411  {
2412  //Implement HT immediate Block Ack support for HT Delayed Block Ack is not added yet
2413  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), seqNumber))
2414  {
2415  StoreMpduIfNeeded (packet, hdr);
2416  if (!IsInWindow (hdr.GetSequenceNumber (), (*it).second.first.GetStartingSequence (), (*it).second.first.GetBufferSize ()))
2417  {
2418  uint16_t delta = (seqNumber - (*it).second.first.GetWinEnd () + 4096) % 4096;
2419  if (delta > 1)
2420  {
2421  (*it).second.first.SetWinEnd (seqNumber);
2422  int16_t winEnd = (*it).second.first.GetWinEnd ();
2423  int16_t bufferSize = (*it).second.first.GetBufferSize ();
2424  uint16_t sum = ((uint16_t)(std::abs (winEnd - bufferSize + 1))) % 4096;
2425  (*it).second.first.SetStartingSequence (sum);
2426  RxCompleteBufferedPacketsWithSmallerSequence ((*it).second.first.GetStartingSequenceControl (), originator, tid);
2427  }
2428  }
2429  RxCompleteBufferedPacketsUntilFirstLost (originator, tid); //forwards up packets starting from winstart and set winstart to last +1
2430  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2431  }
2432  return true;
2433  }
2434  return false;
2435  }
2436  else
2437  {
2438  return StoreMpduIfNeeded (packet, hdr);
2439  }
2440 }
2441 
2442 bool
2444 {
2445  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2446  if (it != m_bAckAgreements.end ())
2447  {
2448  WifiMacTrailer fcs;
2449  packet->RemoveTrailer (fcs);
2450  BufferedPacket bufferedPacket (packet, hdr);
2451 
2452  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2453  uint16_t mappedSeqControl = QosUtilsMapSeqControlToUniqueInteger (hdr.GetSequenceControl (), endSequence);
2454 
2455  BufferedPacketI i = (*it).second.second.begin ();
2456  for (; i != (*it).second.second.end ()
2457  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceControl (), endSequence) < mappedSeqControl; i++)
2458  {
2459  }
2460  (*it).second.second.insert (i, bufferedPacket);
2461 
2462  //Update block ack cache
2463  BlockAckCachesI j = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2464  NS_ASSERT (j != m_bAckCaches.end ());
2465  (*j).second.UpdateWithMpdu (&hdr);
2466  return true;
2467  }
2468  return false;
2469 }
2470 
2471 void
2473  uint16_t startingSeq)
2474 {
2475  uint8_t tid = respHdr->GetTid ();
2476  BlockAckAgreement agreement (originator, tid);
2477  if (respHdr->IsImmediateBlockAck ())
2478  {
2479  agreement.SetImmediateBlockAck ();
2480  }
2481  else
2482  {
2483  agreement.SetDelayedBlockAck ();
2484  }
2485  agreement.SetAmsduSupport (respHdr->IsAmsduSupported ());
2486  agreement.SetBufferSize (respHdr->GetBufferSize () + 1);
2487  agreement.SetTimeout (respHdr->GetTimeout ());
2488  agreement.SetStartingSequence (startingSeq);
2489 
2490  std::list<BufferedPacket> buffer (0);
2491  AgreementKey key (originator, respHdr->GetTid ());
2492  AgreementValue value (agreement, buffer);
2493  m_bAckAgreements.insert (std::make_pair (key, value));
2494 
2495  BlockAckCache cache;
2496  cache.Init (startingSeq, respHdr->GetBufferSize () + 1);
2497  m_bAckCaches.insert (std::make_pair (key, cache));
2498 
2499  if (respHdr->GetTimeout () != 0)
2500  {
2501  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, respHdr->GetTid ()));
2502  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2503 
2504  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2505 
2506  it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
2508  m_edcaListeners[ac],
2509  originator, tid);
2510  }
2511 }
2512 
2513 void
2515 {
2516  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2517  if (it != m_bAckAgreements.end ())
2518  {
2519  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (), originator, tid);
2520  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2521  m_bAckAgreements.erase (it);
2522 
2523  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2524  NS_ASSERT (i != m_bAckCaches.end ());
2525  m_bAckCaches.erase (i);
2526  }
2527 }
2528 
2529 void
2531 {
2532  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2533  if (it != m_bAckAgreements.end ())
2534  {
2535  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2536  uint16_t mappedStart = QosUtilsMapSeqControlToUniqueInteger (seq, endSequence);
2537  BufferedPacketI last = (*it).second.second.begin ();
2538  uint16_t guard = 0;
2539  if (last != (*it).second.second.end ())
2540  {
2541  guard = (*it).second.second.begin ()->second.GetSequenceControl ();
2542  }
2543  BufferedPacketI i = (*it).second.second.begin ();
2544  for (; i != (*it).second.second.end ()
2545  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceControl (), endSequence) < mappedStart; )
2546  {
2547  if (guard == (*i).second.GetSequenceControl ())
2548  {
2549  if (!(*i).second.IsMoreFragments ())
2550  {
2551  while (last != i)
2552  {
2553  m_rxCallback ((*last).first, &(*last).second);
2554  last++;
2555  }
2556  m_rxCallback ((*last).first, &(*last).second);
2557  last++;
2558  /* go to next packet */
2559  while (i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl ())
2560  {
2561  i++;
2562  }
2563  if (i != (*it).second.second.end ())
2564  {
2565  guard = (*i).second.GetSequenceControl ();
2566  last = i;
2567  }
2568  }
2569  else
2570  {
2571  guard++;
2572  }
2573  }
2574  else
2575  {
2576  /* go to next packet */
2577  while (i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl ())
2578  {
2579  i++;
2580  }
2581  if (i != (*it).second.second.end ())
2582  {
2583  guard = (*i).second.GetSequenceControl ();
2584  last = i;
2585  }
2586  }
2587  }
2588  (*it).second.second.erase ((*it).second.second.begin (), i);
2589  }
2590 }
2591 
2592 void
2594 {
2595  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2596  if (it != m_bAckAgreements.end ())
2597  {
2598  uint16_t guard = (*it).second.first.GetStartingSequenceControl ();
2599  BufferedPacketI lastComplete = (*it).second.second.begin ();
2600  BufferedPacketI i = (*it).second.second.begin ();
2601  for (; i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl (); i++)
2602  {
2603  if (!(*i).second.IsMoreFragments ())
2604  {
2605  while (lastComplete != i)
2606  {
2607  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2608  lastComplete++;
2609  }
2610  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2611  lastComplete++;
2612  }
2613  guard = (*i).second.IsMoreFragments () ? (guard + 1) : ((guard + 16) & 0xfff0);
2614  }
2615  (*it).second.first.SetStartingSequenceControl (guard);
2616  /* All packets already forwarded to WifiMac must be removed from buffer:
2617  [begin (), lastComplete) */
2618  (*it).second.second.erase ((*it).second.second.begin (), lastComplete);
2619  }
2620 }
2621 void
2622 MacLow::SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate,
2623  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2624 {
2625  Ptr<Packet> packet = Create<Packet> ();
2626  packet->AddHeader (*blockAck);
2627 
2628  WifiMacHeader hdr;
2630  hdr.SetAddr1 (originator);
2631  hdr.SetAddr2 (GetAddress ());
2632  hdr.SetDsNotFrom ();
2633  hdr.SetDsNotTo ();
2634  hdr.SetNoRetry ();
2635  hdr.SetNoMoreFragments ();
2636 
2637  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (originator, blockAckReqTxMode);
2638 
2639  m_currentPacket = packet;
2640  m_currentHdr = hdr;
2641  if (immediate)
2642  {
2644  duration -= GetSifs ();
2645  if (blockAck->IsBasic ())
2646  {
2647  duration -= GetBlockAckDuration (originator, blockAckReqTxVector, BASIC_BLOCK_ACK);
2648  }
2649  else if (blockAck->IsCompressed ())
2650  {
2651  duration -= GetBlockAckDuration (originator, blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2652  }
2653  else if (blockAck->IsMultiTid ())
2654  {
2655  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2656  }
2657  }
2658  else
2659  {
2660  m_txParams.EnableAck ();
2661  duration += GetSifs ();
2662  duration += GetAckDuration (originator, blockAckReqTxVector);
2663  }
2665 
2666  if (!immediate)
2667  {
2668  StartDataTxTimers (blockAckReqTxVector);
2669  }
2670 
2671  NS_ASSERT (duration >= MicroSeconds (0));
2672  hdr.SetDuration (duration);
2673  //here should be present a control about immediate or delayed block ack
2674  //for now we assume immediate
2675  packet->AddHeader (hdr);
2676  WifiMacTrailer fcs;
2677  packet->AddTrailer (fcs);
2678  WifiPreamble preamble;
2679  if (blockAckReqTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
2680  {
2681  preamble = WIFI_PREAMBLE_HT_MF;
2682  }
2684  {
2685  preamble = WIFI_PREAMBLE_SHORT;
2686  }
2687  else
2688  {
2689  preamble = WIFI_PREAMBLE_LONG;
2690  }
2691  SnrTag tag;
2692  tag.Set (rxSnr);
2693  packet->AddPacketTag (tag);
2694  ForwardDown (packet, &hdr, blockAckReqTxVector, preamble);
2695  m_currentPacket = 0;
2696 }
2697 
2698 void
2699 MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector, double rxSnr)
2700 {
2701  NS_LOG_FUNCTION (this << (uint16_t) tid << originator << duration.As (Time::S) << blockAckReqTxVector << rxSnr);
2702  CtrlBAckResponseHeader blockAck;
2703  uint16_t seqNumber = 0;
2704  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2705  NS_ASSERT (i != m_bAckCaches.end ());
2706  seqNumber = (*i).second.GetWinStart ();
2707 
2708  bool immediate = true;
2709  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2710  blockAck.SetStartingSequence (seqNumber);
2711  blockAck.SetTidInfo (tid);
2712  immediate = (*it).second.first.IsImmediateBlockAck ();
2713  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2714  NS_LOG_DEBUG ("Got Implicit block Ack Req with seq " << seqNumber);
2715  (*i).second.FillBlockAckBitmap (&blockAck);
2716 
2717  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxVector.GetMode (), rxSnr);
2718 }
2719 
2720 void
2722  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2723 {
2724  NS_LOG_FUNCTION (this);
2725  CtrlBAckResponseHeader blockAck;
2726  uint8_t tid = 0;
2727  bool immediate = false;
2728  if (!reqHdr.IsMultiTid ())
2729  {
2730  tid = reqHdr.GetTidInfo ();
2731  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2732  if (it != m_bAckAgreements.end ())
2733  {
2734  blockAck.SetStartingSequence (reqHdr.GetStartingSequence ());
2735  blockAck.SetTidInfo (tid);
2736  immediate = (*it).second.first.IsImmediateBlockAck ();
2737  if (reqHdr.IsBasic ())
2738  {
2739  blockAck.SetType (BASIC_BLOCK_ACK);
2740  }
2741  else if (reqHdr.IsCompressed ())
2742  {
2743  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2744  }
2745  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2746  NS_ASSERT (i != m_bAckCaches.end ());
2747  (*i).second.FillBlockAckBitmap (&blockAck);
2748  NS_LOG_DEBUG ("Got block Ack Req with seq " << reqHdr.GetStartingSequence ());
2749 
2751  {
2752  /* All packets with smaller sequence than starting sequence control must be passed up to Wifimac
2753  * See 9.10.3 in IEEE 802.11e standard.
2754  */
2756  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2757  }
2758  else
2759  {
2760  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), reqHdr.GetStartingSequence ()))
2761  {
2762  (*it).second.first.SetStartingSequence (reqHdr.GetStartingSequence ());
2763  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2765  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2766  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2767  }
2768  }
2769  }
2770  else
2771  {
2772  NS_LOG_DEBUG ("there's not a valid block ack agreement with " << originator);
2773  }
2774  }
2775  else
2776  {
2777  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2778  }
2779 
2780  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode, rxSnr);
2781 }
2782 
2783 void
2785 {
2786  if (agreement.GetTimeout () != 0)
2787  {
2788  NS_ASSERT (agreement.m_inactivityEvent.IsRunning ());
2789  agreement.m_inactivityEvent.Cancel ();
2790  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2791  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2792  agreement.m_inactivityEvent = Simulator::Schedule (timeout,
2794  m_edcaListeners[ac],
2795  agreement.GetPeer (),
2796  agreement.GetTid ());
2797  }
2798 }
2799 
2800 void
2802 {
2803  m_edcaListeners.insert (std::make_pair (ac, listener));
2804 }
2805 
2806 void
2807 MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiTxVector txVector, WifiPreamble preamble)
2808 {
2809  NS_LOG_FUNCTION (this);
2810  AmpduTag ampdu;
2811  bool normalAck = false;
2812  bool ampduSubframe = false; //flag indicating the packet belongs to an A-MPDU and is not a VHT single MPDU
2813  if (aggregatedPacket->RemovePacketTag (ampdu))
2814  {
2815  ampduSubframe = true;
2816  m_currentTxVector = txVector;
2818  MpduAggregator::DeaggregatedMpdusCI n = packets.begin ();
2819 
2820  WifiMacHeader firsthdr;
2821  (*n).first->PeekHeader (firsthdr);
2822  NS_LOG_DEBUG ("duration/id=" << firsthdr.GetDuration ());
2823  NotifyNav ((*n).first, firsthdr, preamble);
2824 
2825  bool vhtSingleMpdu = (*n).second.GetEof ();
2826  if (vhtSingleMpdu)
2827  {
2828  //If the MPDU is sent as a VHT single MPDU (EOF=1 in A-MPDU subframe header), then the responder sends an ACK.
2829  NS_LOG_DEBUG ("Receive VHT single MPDU");
2830  ampduSubframe = false;
2831  }
2832 
2833  if (firsthdr.GetAddr1 () == m_self)
2834  {
2835  if (!vhtSingleMpdu)
2836  {
2837  m_receivedAtLeastOneMpdu = true;
2838  }
2839  if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ())
2840  {
2841  ReceiveOk ((*n).first, rxSnr, txVector, preamble, ampduSubframe);
2842  }
2843  else if (firsthdr.IsData () || firsthdr.IsQosData ())
2844  {
2845  NS_LOG_DEBUG ("Deaggregate packet from " << firsthdr.GetAddr2 () << " with sequence=" << firsthdr.GetSequenceNumber ());
2846  ReceiveOk ((*n).first, rxSnr, txVector, preamble, ampduSubframe);
2847  if (firsthdr.IsQosAck ())
2848  {
2849  NS_LOG_DEBUG ("Normal Ack");
2850  normalAck = true;
2851  }
2852  }
2853  else
2854  {
2855  NS_FATAL_ERROR ("Received A-MPDU with invalid first MPDU type");
2856  }
2857  }
2858 
2859  if (ampdu.GetNoOfMpdus () == 1 && !vhtSingleMpdu)
2860  {
2861  if (normalAck)
2862  {
2863  //send block Ack
2864  if (firsthdr.IsBlockAckReq ())
2865  {
2866  NS_FATAL_ERROR ("Sending a BlockAckReq with QosPolicy equal to Normal Ack");
2867  }
2868  uint8_t tid = firsthdr.GetQosTid ();
2869  AgreementsI it = m_bAckAgreements.find (std::make_pair (firsthdr.GetAddr2 (), tid));
2870  if (it != m_bAckAgreements.end ())
2871  {
2873  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
2874  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
2875  NS_LOG_DEBUG ("rx A-MPDU/sendImmediateBlockAck from=" << firsthdr.GetAddr2 ());
2878  firsthdr.GetQosTid (),
2879  firsthdr.GetAddr2 (),
2880  firsthdr.GetDuration (),
2881  txVector,
2882  rxSnr);
2883  }
2884  else
2885  {
2886  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
2887  }
2888  }
2889  m_receivedAtLeastOneMpdu = false;
2890  }
2891  }
2892  else
2893  {
2894  ReceiveOk (aggregatedPacket, rxSnr, txVector, preamble, ampduSubframe);
2895  }
2896 }
2897 
2898 bool
2899 MacLow::StopMpduAggregation (Ptr<const Packet> peekedPacket, WifiMacHeader peekedHdr, Ptr<Packet> aggregatedPacket, uint16_t size) const
2900 {
2901  if (peekedPacket == 0)
2902  {
2903  NS_LOG_DEBUG ("no more packets in queue");
2904  return true;
2905  }
2906 
2907  WifiPreamble preamble;
2908 
2909  uint8_t tid = GetTid (peekedPacket, peekedHdr);
2910  AcIndex ac = QosUtilsMapTidToAc (tid);
2911  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt = m_edcaListeners.find (ac);
2912 
2914  {
2915  preamble = WIFI_PREAMBLE_VHT;
2916  }
2918  {
2919  preamble = WIFI_PREAMBLE_HT_GF;
2920  }
2922  {
2923  preamble = WIFI_PREAMBLE_HT_MF;
2924  }
2926  {
2927  preamble = WIFI_PREAMBLE_SHORT;
2928  }
2929  else
2930  {
2931  preamble = WIFI_PREAMBLE_LONG;
2932  }
2933 
2934  //An HT STA shall not transmit a PPDU that has a duration that is greater than aPPDUMaxTime (10 milliseconds)
2935  if (m_phy->CalculateTxDuration (aggregatedPacket->GetSize () + peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, m_currentTxVector, preamble, m_phy->GetFrequency ()) > MilliSeconds (10))
2936  {
2937  NS_LOG_DEBUG ("no more packets can be aggregated to satisfy PPDU <= aPPDUMaxTime");
2938  return true;
2939  }
2940 
2941  if (!listenerIt->second->GetMpduAggregator ()->CanBeAggregated (peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, aggregatedPacket, size))
2942  {
2943  NS_LOG_DEBUG ("no more packets can be aggregated because the maximum A-MPDU size has been reached");
2944  return true;
2945  }
2946 
2947  return false;
2948 }
2949 
2952 {
2953  NS_ASSERT (m_aggregateQueue->GetSize () == 0);
2954  bool isAmpdu = false;
2955  Ptr<Packet> newPacket, tempPacket;
2956  WifiMacHeader peekedHdr;
2957  newPacket = packet->Copy ();
2958  Ptr<Packet> currentAggregatedPacket;
2959  CtrlBAckRequestHeader blockAckReq;
2960  //missing hdr.IsAck() since we have no means of knowing the Tid of the Ack yet
2961  if (hdr.IsQosData () || hdr.IsBlockAck ()|| hdr.IsBlockAckReq ())
2962  {
2963  Time tstamp;
2964  uint8_t tid = GetTid (packet, hdr);
2965  Ptr<WifiMacQueue> queue;
2966  AcIndex ac = QosUtilsMapTidToAc (tid);
2967  //since a blockack agreement always preceeds mpdu aggregation there should always exist blockAck listener
2968  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt = m_edcaListeners.find (ac);
2969  NS_ASSERT (listenerIt != m_edcaListeners.end ());
2970  queue = listenerIt->second->GetQueue ();
2971 
2972  if (!hdr.GetAddr1 ().IsBroadcast () && listenerIt->second->GetMpduAggregator () != 0)
2973  {
2974  //Have to make sure that their exist a block Ack agreement before sending an AMPDU (BlockAck Manager)
2975  if (listenerIt->second->GetBlockAckAgreementExists (hdr.GetAddr1 (), tid))
2976  {
2977  /* here is performed mpdu aggregation */
2978  /* MSDU aggregation happened in edca if the user asked for it so m_currentPacket may contains a normal packet or a A-MSDU*/
2979  currentAggregatedPacket = Create<Packet> ();
2980  peekedHdr = hdr;
2981  uint16_t startingSequenceNumber = 0;
2982  uint16_t currentSequenceNumber = 0;
2983  uint8_t qosPolicy = 0;
2984  uint16_t blockAckSize = 0;
2985  bool aggregated = false;
2986  int i = 0;
2987  Ptr<Packet> aggPacket = newPacket->Copy ();
2988 
2989  if (!hdr.IsBlockAckReq ())
2990  {
2991  if (!hdr.IsBlockAck ())
2992  {
2993  startingSequenceNumber = peekedHdr.GetSequenceNumber ();
2994  peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
2995  }
2996  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
2997  newPacket->AddHeader (peekedHdr);
2998  WifiMacTrailer fcs;
2999  newPacket->AddTrailer (fcs);
3000 
3001  aggregated = listenerIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
3002 
3003  if (aggregated)
3004  {
3005  NS_LOG_DEBUG ("Adding packet with Sequence number " << peekedHdr.GetSequenceNumber () << " to A-MPDU, packet size = " << newPacket->GetSize () << ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
3006  i++;
3007  m_sentMpdus++;
3008  m_aggregateQueue->Enqueue (aggPacket, peekedHdr);
3009  }
3010  }
3011  else if (hdr.IsBlockAckReq ())
3012  {
3013  blockAckSize = packet->GetSize () + hdr.GetSize () + WIFI_MAC_FCS_LENGTH;
3014  qosPolicy = 3; //if the last subrame is block ack req then set ack policy of all frames to blockack
3015  packet->PeekHeader (blockAckReq);
3016  startingSequenceNumber = blockAckReq.GetStartingSequence ();
3017  }
3018  aggregated = false;
3019  bool retry = false;
3020  //looks for other packets to the same destination with the same Tid need to extend that to include MSDUs
3021  Ptr<const Packet> peekedPacket = listenerIt->second->PeekNextPacketInBaQueue (peekedHdr, peekedHdr.GetAddr1 (), tid, &tstamp);
3022  if (peekedPacket == 0)
3023  {
3024  peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
3026  hdr.GetAddr1 (), &tstamp);
3027  currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr);
3028 
3029  /* here is performed MSDU aggregation (two-level aggregation) */
3030  if (peekedPacket != 0 && listenerIt->second->GetMsduAggregator () != 0)
3031  {
3032  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
3033  if (tempPacket != 0) //MSDU aggregation
3034  {
3035  peekedPacket = tempPacket->Copy ();
3036  }
3037  }
3038  }
3039  else
3040  {
3041  retry = true;
3042  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
3043  }
3044 
3045  while (IsInWindow (currentSequenceNumber, startingSequenceNumber, 64) && !StopMpduAggregation (peekedPacket, peekedHdr, currentAggregatedPacket, blockAckSize))
3046  {
3047  //for now always send AMPDU with normal ACK
3048  if (retry == false)
3049  {
3050  currentSequenceNumber = listenerIt->second->GetNextSequenceNumberfor (&peekedHdr);
3051  peekedHdr.SetSequenceNumber (currentSequenceNumber);
3052  peekedHdr.SetFragmentNumber (0);
3053  peekedHdr.SetNoMoreFragments ();
3054  peekedHdr.SetNoRetry ();
3055  }
3056  if (qosPolicy == 0)
3057  {
3058  peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
3059  }
3060  else
3061  {
3062  peekedHdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK);
3063  }
3064 
3065  newPacket = peekedPacket->Copy ();
3066  Ptr<Packet> aggPacket = newPacket->Copy ();
3067 
3068  newPacket->AddHeader (peekedHdr);
3069  WifiMacTrailer fcs;
3070  newPacket->AddTrailer (fcs);
3071  aggregated = listenerIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
3072  if (aggregated)
3073  {
3074  m_aggregateQueue->Enqueue (aggPacket, peekedHdr);
3075  if (i == 1 && hdr.IsQosData ())
3076  {
3077  if (!m_txParams.MustSendRts ())
3078  {
3079  listenerIt->second->CompleteMpduTx (packet, hdr, tstamp);
3080  }
3081  else
3082  {
3083  InsertInTxQueue (packet, hdr, tstamp);
3084  }
3085  }
3086  NS_LOG_DEBUG ("Adding packet with Sequence number " << peekedHdr.GetSequenceNumber () << " to A-MPDU, packet size = " << newPacket->GetSize () << ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
3087  i++;
3088  isAmpdu = true;
3089  m_sentMpdus++;
3090  if (!m_txParams.MustSendRts ())
3091  {
3092  listenerIt->second->CompleteMpduTx (peekedPacket, peekedHdr, tstamp);
3093  }
3094  else
3095  {
3096  InsertInTxQueue (peekedPacket, peekedHdr, tstamp);
3097  }
3098  if (retry)
3099  {
3100  listenerIt->second->RemoveFromBaQueue (tid, hdr.GetAddr1 (), peekedHdr.GetSequenceNumber ());
3101  }
3102  else
3103  {
3104  queue->Remove (peekedPacket);
3105  }
3106  newPacket = 0;
3107  }
3108  else
3109  {
3110  break;
3111  }
3112  if (retry == true)
3113  {
3114  peekedPacket = listenerIt->second->PeekNextPacketInBaQueue (peekedHdr, hdr.GetAddr1 (), tid, &tstamp);
3115  if (peekedPacket == 0)
3116  {
3117  //I reached the first packet that I added to this A-MPDU
3118  retry = false;
3119  peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
3120  WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp);
3121  if (peekedPacket != 0)
3122  {
3123  //find what will the sequence number be so that we don't send more than 64 packets apart
3124  currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr);
3125 
3126  if (listenerIt->second->GetMsduAggregator () != 0)
3127  {
3128  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
3129  if (tempPacket != 0) //MSDU aggregation
3130  {
3131  peekedPacket = tempPacket->Copy ();
3132  }
3133  }
3134  }
3135  }
3136  else
3137  {
3138  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
3139  }
3140  }
3141  else
3142  {
3143  peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
3144  WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp);
3145  if (peekedPacket != 0)
3146  {
3147  //find what will the sequence number be so that we don't send more than 64 packets apart
3148  currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr);
3149 
3150  if (listenerIt->second->GetMsduAggregator () != 0 && IsInWindow (currentSequenceNumber, startingSequenceNumber, 64))
3151  {
3152  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
3153  if (tempPacket != 0) //MSDU aggregation
3154  {
3155  peekedPacket = tempPacket->Copy ();
3156  }
3157  }
3158  }
3159  }
3160  }
3161 
3162  if (isAmpdu)
3163  {
3164  if (hdr.IsBlockAckReq ())
3165  {
3166  newPacket = packet->Copy ();
3167  peekedHdr = hdr;
3168  Ptr<Packet> aggPacket = newPacket->Copy ();
3169  m_aggregateQueue->Enqueue (aggPacket, peekedHdr);
3170  newPacket->AddHeader (peekedHdr);
3171  WifiMacTrailer fcs;
3172  newPacket->AddTrailer (fcs);
3173  listenerIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
3174  currentAggregatedPacket->AddHeader (blockAckReq);
3175  }
3176  if (qosPolicy == 0)
3177  {
3178  listenerIt->second->CompleteTransfer (hdr.GetAddr1 (), tid);
3179  }
3180  //Add packet tag
3181  AmpduTag ampdutag;
3182  ampdutag.SetAmpdu (true);
3183  ampdutag.SetNoOfMpdus (i);
3184  newPacket = currentAggregatedPacket;
3185  newPacket->AddPacketTag (ampdutag);
3186  NS_LOG_DEBUG ("tx unicast A-MPDU");
3187  listenerIt->second->SetAmpdu (hdr.GetAddr1 (), true);
3188  }
3189  else
3190  {
3191  uint32_t queueSize = m_aggregateQueue->GetSize ();
3192  NS_ASSERT (queueSize <= 2); //since it is not an A-MPDU then only 2 packets should have been added to the queue no more
3193  if (queueSize >= 1)
3194  {
3195  //remove any packets that we added to the aggregate queue
3197  }
3198  }
3199  }
3200  //VHT single MPDU operation
3202  if (!isAmpdu && dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_VHT && hdr.IsQosData ())
3203  {
3204  peekedHdr = hdr;
3206 
3207  currentAggregatedPacket = Create<Packet> ();
3208  listenerIt->second->GetMpduAggregator ()->AggregateVhtSingleMpdu (packet, currentAggregatedPacket);
3209  m_aggregateQueue->Enqueue (packet, peekedHdr);
3210  m_sentMpdus = 1;
3211 
3212  if (listenerIt->second->GetBlockAckAgreementExists (hdr.GetAddr1 (), tid))
3213  {
3214  listenerIt->second->CompleteTransfer (peekedHdr.GetAddr1 (), tid);
3215  }
3216 
3217  //Add packet tag
3218  AmpduTag ampdutag;
3219  ampdutag.SetAmpdu (true);
3220  ampdutag.SetNoOfMpdus (1);
3221 
3222  newPacket = currentAggregatedPacket;
3223  newPacket->AddHeader (peekedHdr);
3224  WifiMacTrailer fcs;
3225  newPacket->AddTrailer (fcs);
3226  newPacket->AddPacketTag (ampdutag);
3227 
3228  NS_LOG_DEBUG ("tx unicast VHT single MPDU with sequence number " << hdr.GetSequenceNumber ());
3229  listenerIt->second->SetAmpdu (hdr.GetAddr1 (), true);
3230  }
3231  }
3232  }
3233  return newPacket;
3234 }
3235 
3236 void
3238 {
3239  if (m_aggregateQueue->GetSize () > 0)
3240  {
3241  NS_LOG_DEBUG ("Flush aggregate queue");
3242  m_aggregateQueue->Flush ();
3243  }
3244  m_txPackets.clear ();
3245 }
3246 
3247 void
3249 {
3250  Item item;
3251 
3252  item.packet = packet;
3253  item.hdr = hdr;
3254  item.timestamp = tStamp;
3255 
3256  m_txPackets.push_back (item);
3257 }
3258 
3260 MacLow::PerformMsduAggregation (Ptr<const Packet> packet, WifiMacHeader *hdr, Time *tstamp, Ptr<Packet> currentAmpduPacket, uint16_t blockAckSize)
3261 {
3262  bool msduAggregation = false;
3263  bool isAmsdu = false;
3264  Ptr<Packet> currentAmsduPacket = Create<Packet> ();
3265  Ptr<Packet> tempPacket = Create<Packet> ();
3266 
3267  Ptr<WifiMacQueue> queue;
3268  AcIndex ac = QosUtilsMapTidToAc (GetTid (packet, *hdr));
3269  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt = m_edcaListeners.find (ac);
3270  NS_ASSERT (listenerIt != m_edcaListeners.end ());
3271  queue = listenerIt->second->GetQueue ();
3272 
3273  Ptr<const Packet> peekedPacket = queue->DequeueByTidAndAddress (hdr, hdr->GetQosTid (),
3274  WifiMacHeader::ADDR1, hdr->GetAddr1 ());
3275 
3276  listenerIt->second->GetMsduAggregator ()->Aggregate (packet, currentAmsduPacket,
3277  listenerIt->second->GetSrcAddressForAggregation (*hdr),
3278  listenerIt->second->GetDestAddressForAggregation (*hdr));
3279 
3280  peekedPacket = queue->PeekByTidAndAddress (hdr, hdr->GetQosTid (),
3281  WifiMacHeader::ADDR1, hdr->GetAddr1 (), tstamp);
3282  while (peekedPacket != 0)
3283  {
3284  tempPacket = currentAmsduPacket;
3285 
3286  msduAggregation = listenerIt->second->GetMsduAggregator ()->Aggregate (peekedPacket, tempPacket,
3287  listenerIt->second->GetSrcAddressForAggregation (*hdr),
3288  listenerIt->second->GetDestAddressForAggregation (*hdr));
3289 
3290  if (msduAggregation && !StopMpduAggregation (tempPacket, *hdr, currentAmpduPacket, blockAckSize))
3291  {
3292  isAmsdu = true;
3293  currentAmsduPacket = tempPacket;
3294  queue->Remove (peekedPacket);
3295  }
3296  else
3297  {
3298  break;
3299  }
3300  peekedPacket = queue->PeekByTidAndAddress (hdr, hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 (), tstamp);
3301  }
3302 
3303  if (isAmsdu)
3304  {
3305  NS_LOG_DEBUG ("A-MSDU with size = " << currentAmsduPacket->GetSize ());
3306  hdr->SetQosAmsdu ();
3307  hdr->SetAddr3 (GetBssid ());
3308  return currentAmsduPacket;
3309  }
3310  else
3311  {
3312  queue->PushFront (packet, *hdr);
3313  return 0;
3314  }
3315 }
3316 
3317 } //namespace ns3
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
void Set(double snr)
Set the SNR to the given value.
Definition: snr-tag.cc:89
bool MustSendRts(void) const
Definition: mac-low.cc:243
Time GetPifs(void) const
Return PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:675
uint32_t GetAckSize(void) const
Return the total ACK size (including FCS trailer).
Definition: mac-low.cc:1248
virtual ~MacLowDcfListener()
Definition: mac-low.cc:65
void SetPifs(Time pifs)
Set PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:603
Time m_ctsTimeout
CTS timeout duration.
Definition: mac-low.h:1343
uint16_t GetBufferSize(void) const
Return the buffer size.
virtual uint32_t GetFrequency(void) const =0
uint8_t GetTid(void) const
Return the Traffic ID (TID).
virtual void SetAmpdu(Mac48Address dest, bool enableAmpdu)
Definition: mac-low.cc:75
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
EventId m_navCounterResetCtsMissed
Event to reset NAV when CTS is not received.
Definition: mac-low.h:1330
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void SetQosAckPolicy(enum QosAckPolicy policy)
Set the QoS ACK policy in the QoS control field.
Ptr< WifiPhy > GetPhy(void) const
Definition: mac-low.cc:528
void ResetBlockAckInactivityTimerIfNeeded(BlockAckAgreement &agreement)
Every time that a block ack request or a packet with ack policy equals to block ack are received...
Definition: mac-low.cc:2784
bool GetGreenfieldSupported(Mac48Address address) const
Return whether the station supports Greenfield or not.
EventId m_blockAckTimeoutEvent
Block ACK timeout event.
Definition: mac-low.h:1323
Time GetBlockAckDuration(Mac48Address to, WifiTxVector blockAckReqTxVector, enum BlockAckType type) const
Return the time required to transmit the Block ACK to the specified address given the TXVECTOR of the...
Definition: mac-low.cc:1309
Callback template class.
Definition: callback.h:1164
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
virtual ~MacLowTransmissionListener()
Definition: mac-low.cc:50
uint16_t GetTimeout(void) const
Return the timeout.
Time GetAckDuration(WifiTxVector ackTxVector) const
Return the time required to transmit the ACK (including preamble and FCS).
Definition: mac-low.cc:1293
void SendBlockAckAfterBlockAckRequest(const CtrlBAckRequestHeader reqHdr, Mac48Address originator, Time duration, WifiMode blockAckReqTxMode, double rxSnr)
Invoked after that a block ack request has been received.
Definition: mac-low.cc:2721
virtual void GotAck(double snr, WifiMode txMode)=0
virtual Ptr< const Packet > PeekNextPacketInBaQueue(WifiMacHeader &header, Mac48Address recipient, uint8_t tid, Time *timestamp)
Definition: mac-low.cc:96
bool IsBasic(void) const
Check if the current ACK policy is basic (i.e.
void SetDuration(Time duration)
Set the Duration/ID field with the given duration (Time object).
void SetPromisc(void)
Enable promiscuous mode.
Definition: mac-low.cc:621
EventId m_waitSifsEvent
Wait for SIFS event.
Definition: mac-low.h:1328
void DoNavResetNow(Time duration)
Reset NAV with the given duration.
Definition: mac-low.cc:1576
virtual Mac48Address GetDestAddressForAggregation(const WifiMacHeader &hdr)
Definition: mac-low.cc:130
void ReportDataFailed(Mac48Address address, const WifiMacHeader *header)
Should be invoked whenever the AckTimeout associated to a transmission attempt expires.
bool IsPromisc(void) const
Check if MacLow is operating in promiscuous mode.
Definition: mac-low.cc:687
bool m_receivedAtLeastOneMpdu
Flag whether an MPDU has already been successfully received while receiving an A-MPDU.
Definition: mac-low.h:1381
bool GetUseNonErpProtection(void) const
Return whether the device supports protection of non-ERP stations.
void EnableBasicBlockAck(void)
Wait BASICBLOCKACKTimeout for a Basic Block Ack Response frame.
Definition: mac-low.cc:168
Mac48Address GetPeer(void) const
Return the peer address.
EventId m_fastAckTimeoutEvent
Fast ACK timeout event.
Definition: mac-low.h:1320
Time m_pifs
PCF Interframe Space (PIFS) duration.
Definition: mac-low.h:1346
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:824
bool DoNavStartNow(Time duration)
Start NAV with the given duration.
Definition: mac-low.cc:1587
void FastAckFailedTimeout(void)
Event handler when fast ACK timeout occurs (busy).
Definition: mac-low.cc:2339
Mac48Address GetBssid(void) const
Return the Basic Service Set Identification.
Definition: mac-low.cc:681
void SetSifs(Time sifs)
Set Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:591
virtual void MissedAck(void)=0
ns3::MacLow did not receive an expected ACK within AckTimeout.
std::pair< Mac48Address, uint8_t > AgreementKey
Definition: mac-low.h:1363
enum WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:386
WifiTxVector GetCtsToSelfTxVector(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return a TXVECTOR for the CTS-to-self frame.
Definition: mac-low.cc:1379
void SetNoMoreFragments(void)
Un-set the More Fragment bit in the Frame Control Field.
bool IsImmediateBlockAck(void) const
Return whether the Block ACK policy is immediate Block ACK.
void RegisterBlockAckListenerForAc(enum AcIndex ac, MacLowAggregationCapableTransmissionListener *listener)
Definition: mac-low.cc:2801
void SetupPhyMacLowListener(Ptr< WifiPhy > phy)
Set up WifiPhy listener for this MacLow.
Definition: mac-low.cc:401
WifiTxVector GetCtsTxVector(Mac48Address address, WifiMode rtsMode)
virtual void MissedBlockAck(uint32_t nMpdus)
Definition: mac-low.cc:58
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
void Init(uint16_t winStart, uint16_t winSize)
static const uint16_t WIFI_MAC_FCS_LENGTH
The length in octects of the IEEE 802.11 MAC FCS field.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
bool IsMultiTid(void) const
Check if the current ACK policy has multiple TID.
virtual void NotifyRxEndError(void)
We have received the last bit of a packet for which NotifyRxStart was invoked first and...
Definition: mac-low.cc:330
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:903
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:786
static DeaggregatedMpdus Deaggregate(Ptr< Packet > aggregatedPacket)
Deaggregates an A-MPDU by removing the A-MPDU subframe header and padding.
bool IsBroadcast(void) const
second
Definition: nstime.h:114
void NotifySleepNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:901
uint8_t GetTid(Ptr< const Packet > packet, const WifiMacHeader hdr) const
Definition: mac-low.cc:1225
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
bool HasDurationId(void) const
Definition: mac-low.cc:248
std::list< std::pair< Ptr< Packet >, AmpduSubframeHeader > >::const_iterator DeaggregatedMpdusCI
A constant iterator for a list of deaggregated packets and their A-MPDU subframe headers.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:145
bool QosUtilsIsOldPacket(uint16_t startingSeq, uint16_t seqNumber)
This function checks if packet with sequence number seqNumber is an "old" packet. ...
Definition: qos-utils.cc:88
DcfListeners m_dcfListeners
List of MacLowDcfListener (pass events to Dcf)
Definition: mac-low.h:1317
uint8_t m_sentMpdus
Number of transmitted MPDUs in an A-MPDU that have not been acknowledged yet.
Definition: mac-low.h:1378
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:719
bool IsBlockAck(void) const
Return true if the header is a Block ACK header.
bool m_ampdu
Flag if the current transmission involves an A-MPDU.
Definition: mac-low.h:1353
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
bool NeedRts(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, WifiTxVector txVector)
void SetRxCallback(Callback< void, Ptr< Packet >, const WifiMacHeader * > callback)
Definition: mac-low.cc:693
void DeaggregateAmpduAndReceive(Ptr< Packet > aggregatedPacket, double rxSnr, WifiTxVector txVector, WifiPreamble preamble)
Definition: mac-low.cc:2807
Time GetCompressedBlockAckTimeout() const
Return Compressed Block ACK timeout of this MacLow.
Definition: mac-low.cc:645
Callback< R > MakeNullCallback(void)
Definition: callback.h:1626
VHT PHY (Clause 22)
Definition: wifi-mode.h:64
Mac48Address m_bssid
BSSID address (Mac48Address)
Definition: mac-low.h:1339
ns3::Time timeout
virtual void BlockAckInactivityTimeout(Mac48Address originator, uint8_t tid)=0
Typically is called in order to notify EdcaTxopN that a block ack inactivity timeout occurs for the b...
BlockAckType
Enumeration for different block ACK policies.
Definition: ctrl-headers.h:31
Ptr< Packet > AggregateToAmpdu(Ptr< const Packet > packet, const WifiMacHeader hdr)
Definition: mac-low.cc:2951
EventId m_sendCtsEvent
Event to send CTS.
Definition: mac-low.h:1325
MacLowRxCallback m_rxCallback
Callback to pass packet up.
Definition: mac-low.h:1297
Time GetCtsTimeout(void) const
Return CTS timeout of this MacLow.
Definition: mac-low.cc:651
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
EventId m_superFastAckTimeoutEvent
Super fast ACK timeout event.
Definition: mac-low.h:1321
EventId m_sendAckEvent
Event to send ACK.
Definition: mac-low.h:1326
listen to events coming from ns3::MacLow.
Definition: mac-low.h:63
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:99
Time GetCtsDuration(WifiTxVector ctsTxVector) const
Return the time required to transmit the CTS (including preamble and FCS).
Definition: mac-low.cc:1339
bool MustWaitFastAck(void) const
Definition: mac-low.cc:218
Ptr< Packet > PerformMsduAggregation(Ptr< const Packet > packet, WifiMacHeader *hdr, Time *tstamp, Ptr< Packet > currentAmpduPacket, uint16_t blockAckSize)
Perform MSDU aggregation for a given MPDU in an A-MPDU.
Definition: mac-low.cc:3260
virtual void RegisterListener(WifiPhyListener *listener)=0
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
control how a packet is transmitted.
Definition: mac-low.h:305
void WaitSifsAfterEndTx(void)
Event handler that is usually scheduled to fired at the appropriate time after completing transmissio...
Definition: mac-low.cc:2325
WifiTxVector GetCtsToSelfTxVector(const WifiMacHeader *header, Ptr< const Packet > packet)
std::vector< MacLowDcfListener * >::const_iterator DcfListenersCI
typedef for an iterator for a list of MacLowDcfListener.
Definition: mac-low.h:1312
bool IsCfpoll(void) const
Return true if the Type/Subtype is one of the possible CF-Poll headers.
virtual void CompleteTransfer(Mac48Address address, uint8_t tid)
Definition: mac-low.cc:78
void SetCtsToSelfSupported(bool enable)
Enable or disable CTS-to-self capability.
Definition: mac-low.cc:573
void NormalAckTimeout(void)
Event handler when normal ACK timeout occurs.
Definition: mac-low.cc:1756
void SetBasicBlockAckTimeout(Time blockAckTimeout)
Set Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:561
bool IsAmsduSupported(void) const
Return whether A-MSDU capability is supported.
void SetNoOfMpdus(uint8_t noofmpdus)
Definition: ampdu-tag.cc:62
BlockAckCaches m_bAckCaches
Definition: mac-low.h:1373
void InsertInTxQueue(Ptr< const Packet > packet, const WifiMacHeader &hdr, Time tStamp)
Insert in a temporary queue.
Definition: mac-low.cc:3248
virtual bool IsStateIdle(void)=0
virtual uint32_t GetNRetryNeededPackets(Mac48Address recipient, uint8_t tid) const
Definition: mac-low.cc:110
Time GetDuration(void) const
Return the duration from the Duration/ID field (Time object).
void RemovePhyMacLowListener(Ptr< WifiPhy > phy)
Remove current WifiPhy listener for this MacLow.
Definition: mac-low.cc:408
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
Definition: wifi-preamble.h:30
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
virtual void RemoveFromBaQueue(uint8_t tid, Mac48Address recipient, uint16_t seqnumber)
Remove a packet after you peek in the retransmit queue and get it.
Definition: mac-low.cc:101
WifiTxVector m_currentTxVector
TXVECTOR used for the current packet transmission.
Definition: mac-low.h:1380
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
void DestroyBlockAckAgreement(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2514
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:846
Time m_lastNavDuration
The duration of the latest NAV.
Definition: mac-low.h:1350
virtual uint32_t GetSerializedSize(void) const
The MPDU is not part of an A-MPDU.
Definition: wifi-phy.h:48
std::pair< Ptr< Packet >, WifiMacHeader > BufferedPacket
Definition: mac-low.h:1360
void SendCtsToSelf(void)
Send CTS for a CTS-to-self mechanism.
Definition: mac-low.cc:2087
bool m_ctsToSelfSupported
Flag whether CTS-to-self is supported.
Definition: mac-low.h:1377
tuple phy
Definition: third.py:86
void SetAmpdu(bool supported)
Set m_ampdu to 1.
Definition: ampdu-tag.cc:56
virtual void SetReceiveErrorCallback(RxErrorCallback callback)=0
void SendAckAfterData(Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
Send ACK after receiving DATA.
Definition: mac-low.cc:2349
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1216
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual Mac48Address GetSrcAddressForAggregation(const WifiMacHeader &hdr)
Definition: mac-low.cc:125
#define max(a, b)
Definition: 80211b.c:45
void CreateBlockAckAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address originator, uint16_t startingSeq)
Definition: mac-low.cc:2472
Ptr< WifiMacQueue > m_aggregateQueue
Queue used for MPDU aggregation.
Definition: mac-low.h:1379
void NotifyNav(Ptr< const Packet > packet, const WifiMacHeader &hdr, WifiPreamble preamble)
Definition: mac-low.cc:1525
virtual void NotifyTxStart(Time duration, double txPowerDbm)
Definition: mac-low.cc:333
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
uint32_t GetBlockAckSize(enum BlockAckType type) const
Return the total Block ACK size (including FCS trailer).
Definition: mac-low.cc:1256
void ReportRtsFailed(Mac48Address address, const WifiMacHeader *header)
Should be invoked whenever the RtsTimeout associated to a transmission attempt expires.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
Listener for PHY events.
Definition: mac-low.cc:309
virtual void NotifyWakeup(void)
Notify listeners that we woke up.
Definition: mac-low.cc:347
receive notifications about phy events.
Definition: wifi-phy.h:70
void CtsTimeout(void)
Event handler when CTS timeout occurs.
Definition: mac-low.cc:1736
virtual void StartNext(void)=0
Invoked when ns3::MacLow wants to start a new transmission as configured by MacLowTransmissionParamet...
uint16_t GetSequenceControl(void) const
Return the raw Sequence Control field.
void EndTxNoAck(void)
A transmission that does not require an ACK has completed.
Definition: mac-low.cc:2331
void SendBlockAckAfterAmpdu(uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector, double rxSnr)
Invoked after an A-MPDU has been received.
Definition: mac-low.cc:2699
std::map< AgreementKey, BlockAckCache >::iterator BlockAckCachesI
Definition: mac-low.h:1370
virtual void EndTxNoAck(void)=0
Invoked upon the end of the transmission of a frame that does not require an ACK (e.g., broadcast and multicast frames).
WifiTxVector GetAckTxVector(Mac48Address to, WifiMode dataTxMode) const
Return a TXVECTOR for the ACK frame given the destination and the mode of the DATA used by the sender...
Definition: mac-low.cc:1406
void SetAckTimeout(Time ackTimeout)
Set ACK timeout of this MacLow.
Definition: mac-low.cc:555
static TypeId GetTypeId(void)
Register this type.
Definition: mac-low.cc:390
virtual uint32_t GetNOutstandingPackets(Mac48Address recipient, uint8_t tid)
Definition: mac-low.cc:105
virtual void GotCts(double snr, WifiMode txMode)=0
void SendDataAfterCts(Mac48Address source, Time duration)
Send DATA after receiving CTS.
Definition: mac-low.cc:2225
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:28
Time GetRifs(void) const
Return Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:663
HT PHY (Clause 20)
Definition: wifi-mode.h:62
virtual void NotifyRxStart(Time duration)
Definition: mac-low.cc:324
virtual void NotifySleep(void)
Notify listeners that we went to sleep.
Definition: mac-low.cc:343
void NavCounterResetCtsMissed(Time rtsEndRxTime)
Reset NAV after CTS was missed when the NAV was setted with RTS.
Definition: mac-low.cc:1567
Time CalculateTxDuration(uint32_t size, WifiTxVector txVector, enum WifiPreamble preamble, double frequency)
Definition: wifi-phy.cc:717
Ptr< WifiRemoteStationManager > m_stationManager
Pointer to WifiRemoteStationManager (rate control)
Definition: mac-low.h:1296
bool MustWaitMultiTidBlockAck(void) const
Definition: mac-low.cc:238
Headers for Block ack response.
Definition: ctrl-headers.h:186
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1480
bool NeedRts(void)
Check if the current packet should be sent with a RTS protection.
Definition: mac-low.cc:827
Mac48Address GetAddress(void) const
Return the MAC address of this MacLow.
Definition: mac-low.cc:627
uint32_t GetNextPacketSize(void) const
Definition: mac-low.cc:264
Agreements m_bAckAgreements
Definition: mac-low.h:1372
uint16_t GetStartingSequenceControl(void) const
Return the starting sequence control.
bool HasNextPacket(void) const
Definition: mac-low.cc:259
The aim of the AmpduTag is to provide means for a MAC to specify that a packet includes A-MPDU since ...
Definition: ampdu-tag.h:36
WifiTxVector GetAckTxVectorForData(Mac48Address to, WifiMode dataTxMode) const
Return a TXVECTOR for the Block ACK frame given the destination and the mode of the DATA used by the ...
Definition: mac-low.cc:1424
virtual uint16_t GetNextSequenceNumberfor(WifiMacHeader *hdr)
Return the next sequence number for the given header.
Definition: mac-low.cc:86
void RegisterDcfListener(MacLowDcfListener *listener)
Definition: mac-low.cc:699
virtual uint32_t GetSerializedSize(void) const
void NotifySwitchingStartNow(Time duration)
Definition: mac-low.cc:885
Time m_slotTime
Slot duration.
Definition: mac-low.h:1345
bool m_promisc
Flag if the device is operating in promiscuous mode.
Definition: mac-low.h:1352
The MPDU is part of an A-MPDU, but is not the last aggregate.
Definition: wifi-phy.h:50
WifiMacHeader hdr
Definition: mac-low.h:1305
void CancelAllEvents(void)
Cancel all scheduled events.
Definition: mac-low.cc:447
virtual void StartTransmission(Ptr< const Packet > packet, const WifiMacHeader *hdr, MacLowTransmissionParameters parameters, MacLowTransmissionListener *listener)
Definition: mac-low.cc:724
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:42
void ReportDataOk(Mac48Address address, const WifiMacHeader *header, double ackSnr, WifiMode ackMode, double dataSnr)
Should be invoked whenever we receive the Ack associated to a data packet we just sent...
std::list< BufferedPacket >::iterator BufferedPacketI
Definition: mac-low.h:1361
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:278
void BlockAckTimeout(void)
Event handler when block ACK timeout occurs.
Definition: mac-low.cc:1791
void NotifyCtsTimeoutStartNow(Time duration)
Notify DcfManager (via DcfListener) that CTS timer should be started for the given duration...
Definition: mac-low.cc:1623
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
virtual void GotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address source, double rxSnr, WifiMode txMode, double dataSnr)
Definition: mac-low.cc:54
void SetNoRetry(void)
Un-set the Retry bit in the Frame Control field.
void EnableCompressedBlockAck(void)
Wait COMPRESSEDBLOCKACKTimeout for a Compressed Block Ack Response frame.
Definition: mac-low.cc:173
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
void SuperFastAckTimeout(void)
Event handler when super fast ACK timeout occurs.
Definition: mac-low.cc:1804
void SetBssid(Mac48Address ad)
Set the Basic Service Set Identification.
Definition: mac-low.cc:615
virtual void UnregisterListener(WifiPhyListener *listener)=0
uint32_t GetRtsSize(void) const
Return the total RTS size (including FCS trailer).
Definition: mac-low.cc:1278
void EnableAck(void)
Wait ACKTimeout for an ACK.
Definition: mac-low.cc:188
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
Time CalculateTransmissionTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &parameters) const
Definition: mac-low.cc:1489
EventId m_normalAckTimeoutEvent
Normal ACK timeout event.
Definition: mac-low.h:1319
void SetType(enum BlockAckType type)
Set the block ACK type.
void StartDataTxTimers(WifiTxVector dataTxVector)
Start a DATA timer by scheduling appropriate ACK timeout.
Definition: mac-low.cc:1909
void AddTrailer(const Trailer &trailer)
Add trailer to this packet.
Definition: packet.cc:285
bool IsBasic(void) const
Check if the current ACK policy is basic (i.e.
void NotifyCtsTimeoutResetNow()
Notify DcfManager (via DcfListener) that CTS timer should be resetted.
Definition: mac-low.cc:1632
bool MustWaitBasicBlockAck(void) const
Definition: mac-low.cc:228
bool MustWaitCompressedBlockAck(void) const
Definition: mac-low.cc:233
uint32_t RemoveTrailer(Trailer &trailer)
Remove a deserialized trailer from the internal buffer.
Definition: packet.cc:296
bool NeedCtsToSelf(void)
Check if CTS-to-self mechanism should be used for the current packet.
Definition: mac-low.cc:835
an EUI-48 address
Definition: mac48-address.h:43
Ptr< const Packet > packet
Definition: mac-low.h:1304
bool HasVhtSupported(void) const
Return whether the device has VHT capability support enabled.
virtual void Cancel(void)=0
Invoked if this transmission was canceled one way or another.
void SendBlockAckResponse(const CtrlBAckResponseHeader *blockAck, Mac48Address originator, bool immediate, Time duration, WifiMode blockAckReqTxMode, double rxSnr)
This method creates block ack frame with header equals to blockAck and start its transmission.
Definition: mac-low.cc:2622
Time m_ackTimeout
ACK timeout duration.
Definition: mac-low.h:1340
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: mac-low.cc:2392
listen to NAV eventsThis class is typically connected to an instance of ns3::Dcf and calls to its met...
Definition: mac-low.h:156
void FastAckTimeout(void)
Event handler when fast ACK timeout occurs (idle).
Definition: mac-low.cc:1773
void DisableRts(void)
Do not send rts and wait for cts before sending data.
Definition: mac-low.cc:203
void EnableMultiTidBlockAck(void)
NOT IMPLEMENTED FOR NOW.
Definition: mac-low.cc:178
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:223
void ReportRtsOk(Mac48Address address, const WifiMacHeader *header, double ctsSnr, WifiMode ctsMode, double rtsSnr)
Should be invoked whenever we receive the Cts associated to an RTS we just sent.
EventId m_ctsTimeoutEvent
CTS timeout event.
Definition: mac-low.h:1324
void RxCompleteBufferedPacketsWithSmallerSequence(uint16_t seq, Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2530
void SendCtsAfterRts(Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
Send CTS after receiving RTS.
Definition: mac-low.cc:2182
void SetPhy(Ptr< WifiPhy > phy)
Set up WifiPhy associated with this MacLow.
Definition: mac-low.cc:519
virtual bool IsStateTx(void)=0
Time m_basicBlockAckTimeout
Basic block ACK timeout duration.
Definition: mac-low.h:1341
void SendMpdu(Ptr< const Packet > packet, WifiTxVector txVector, WifiPreamble preamble, enum mpduType mpdutype)
Forward the MPDU down to WifiPhy for transmission.
Definition: mac-low.cc:1729
Time GetDurationId(void) const
Definition: mac-low.cc:253
uint16_t GetTimeout(void) const
Return the timeout.
uint8_t GetTid(void) const
Return the Traffic ID (TID).
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
virtual void CompleteMpduTx(Ptr< const Packet > packet, WifiMacHeader hdr, Time tstamp)
This function stores an MPDU (part of an A-MPDU) in blockackagreement (i.e.
Definition: mac-low.cc:82
Time m_sifs
Short Interframe Space (SIFS) duration.
Definition: mac-low.h:1344
enum ns3::MacLowTransmissionParameters::@92 m_waitAck
const char * GetTypeString(void) const
Return a string corresponds to the header type.
bool HasHtSupported(void) const
Return whether the device has HT capability support enabled.
Time GetSlotTime(void) const
Return slot duration of this MacLow.
Definition: mac-low.cc:669
WifiMacHeader m_lastReceivedHdr
Header of the last received packet.
Definition: mac-low.h:1335
void SetDelayedBlockAck(void)
Set Block ACK policy to delayed ACK.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:90
Time m_lastNavStart
The time when the latest NAV started.
Definition: mac-low.h:1349
bool NeedCtsToSelf(WifiTxVector txVector)
Return if we need to do Cts-to-self before sending a DATA.
void SetAmsduSupport(bool supported)
Enable or disable A-MSDU support.
virtual void NotifyMaybeCcaBusyStart(Time duration)
Definition: mac-low.cc:336
WifiTxVector GetRtsTxVector(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return a TXVECTOR for the RTS frame given the destination.
Definition: mac-low.cc:1385
virtual WifiTxVector GetDataTxVector(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return a TXVECTOR for the DATA frame given the destination.
Definition: mac-low.cc:1392
handle RTS/CTS/DATA/ACK transactions.
Definition: mac-low.h:494
virtual void MissedCts(void)=0
ns3::MacLow did not receive an expected CTS within CtsTimeout.
std::vector< Item > m_txPackets
Contain temporary items to be sent with the next A-MPDU transmission, once RTS/CTS exchange has succe...
Definition: mac-low.h:1382
EventId m_sendDataEvent
Event to send DATA.
Definition: mac-low.h:1327
bool ReceiveMpdu(Ptr< Packet > packet, WifiMacHeader hdr)
This method updates the reorder buffer and the scoreboard when an MPDU is received in an HT station a...
Definition: mac-low.cc:2398
MacLowTransmissionParameters m_txParams
Transmission parameters of the current packet.
Definition: mac-low.h:1336
void SetRifs(Time rifs)
Set Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:609
virtual void DoDispose(void)
Destructor implementation.
Definition: mac-low.cc:419
void NotifyAckTimeoutResetNow()
Notify DcfManager (via DcfListener) that ACK timer should be resetted.
Definition: mac-low.cc:1614
WifiTxVector GetDataTxVector(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
bool MustWaitSuperFastAck(void) const
Definition: mac-low.cc:223
bool GetShortPreambleEnabled(void) const
Return whether the device uses short PLCP preambles.
TimeWithUnit As(const enum Unit unit) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:388
Time CalculateOverallTxTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &params) const
Definition: mac-low.cc:1430
QueueListeners m_edcaListeners
Definition: mac-low.h:1376
WifiTxVector GetBlockAckTxVector(Mac48Address to, WifiMode dataTxMode) const
Return a TXVECTOR for the Block ACK frame given the destination and the mode of the DATA used by the ...
Definition: mac-low.cc:1412
bool IsData(void) const
Return true if the Type is DATA.
Mac48Address m_self
Address of this MacLow (Mac48Address)
Definition: mac-low.h:1338
Maintains information for a block ack agreement.
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS DATA...
EventId m_fastAckFailedTimeoutEvent
Fast ACK failed timeout event.
Definition: mac-low.h:1322
uint32_t QosUtilsMapSeqControlToUniqueInteger(uint16_t seqControl, uint16_t endSequence)
Next function is useful to correctly sort buffered packets under block ack.
Definition: qos-utils.cc:77
bool IsNavZero(void) const
Check if NAV is zero.
Definition: mac-low.cc:2074
void EnableRts(void)
Send a RTS, and wait CTSTimeout for a CTS.
Definition: mac-low.cc:198
void NotifyAckTimeoutStartNow(Time duration)
Notify DcfManager (via DcfListener) that ACK timer should be started for the given duration...
Definition: mac-low.cc:1605
bool IsBlockAckReq(void) const
Return true if the header is a Block ACK Request header.
void SetSlotTime(Time slotTime)
Set slot duration of this MacLow.
Definition: mac-low.cc:597
Ptr< Packet > m_currentPacket
Current packet transmitted/to be transmitted.
Definition: mac-low.h:1333
Time GetSifs(void) const
Return Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:657
void Reset(void)
Reset the station, invoked in a STA upon dis-association or in an AP upon reboot. ...
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:831
bool StopMpduAggregation(Ptr< const Packet > peekedPacket, WifiMacHeader peekedHdr, Ptr< Packet > aggregatedPacket, uint16_t size) const
Definition: mac-low.cc:2899
Implement the header for management frames of type add block ack response.
Definition: mgt-headers.h:758
ns3::MacLow * m_macLow
Definition: mac-low.cc:351
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:895
std::map< AgreementKey, AgreementValue >::iterator AgreementsI
Definition: mac-low.h:1367
EventId m_endTxNoAckEvent
Event for finishing transmission that does not require ACK.
Definition: mac-low.h:1329
void EnableOverrideDurationId(Time durationId)
Definition: mac-low.cc:153
virtual void SetReceiveOkCallback(RxOkCallback callback)=0
uint32_t m_nTxMpdus
Holds the number of transmitted MPDUs in the last A-MPDU transmission.
Definition: mac-low.h:1383
bool GetCtsToSelfSupported() const
Return whether CTS-to-self capability is supported.
Definition: mac-low.cc:579
void ReportRxOk(Mac48Address address, const WifiMacHeader *header, double rxSnr, WifiMode txMode)
void ReceiveOk(Ptr< Packet > packet, double rxSnr, WifiTxVector txVector, WifiPreamble preamble, bool ampduSubframe)
Definition: mac-low.cc:916
std::list< std::pair< Ptr< Packet >, AmpduSubframeHeader > > DeaggregatedMpdus
A list of deaggregated packets and their A-MPDU subframe headers.
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
void SetCtsTimeout(Time ctsTimeout)
Set CTS timeout of this MacLow.
Definition: mac-low.cc:585
void EnableNextData(uint32_t size)
Definition: mac-low.cc:143
void SetImmediateBlockAck(void)
Set Block ACK policy to immediate ACK.
void DisableOverrideDurationId(void)
Do not force the duration/id field of the packet: its value is automatically calculated by the MacLow...
Definition: mac-low.cc:158
Time GetAckTimeout(void) const
Return ACK timeout of this MacLow.
Definition: mac-low.cc:633
virtual Ptr< MsduAggregator > GetMsduAggregator(void) const
Definition: mac-low.cc:115
virtual uint16_t PeekNextSequenceNumberfor(WifiMacHeader *hdr)
Return the next sequence number for the Traffic ID and destination, but do not pick it (i...
Definition: mac-low.cc:91
EventId m_waitRifsEvent
Wait for RIFS event.
Definition: mac-low.h:1331
void DisableNextData(void)
Do not attempt to send data burst after current transmission.
Definition: mac-low.cc:148
void SendDataPacket(void)
Send DATA packet, which can be DATA-ACK or RTS-CTS-DATA-ACK transaction.
Definition: mac-low.cc:1995
virtual void SendPacket(Ptr< const Packet > packet, WifiTxVector txVector, enum WifiPreamble preamble)=0
void SetTimeout(uint16_t timeout)
Set timeout.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:911
uint32_t GetCtsSize(void) const
Return the total CTS size (including FCS trailer).
Definition: mac-low.cc:1355
WifiMacHeader m_currentHdr
Header of the current transmitted packet.
Definition: mac-low.h:1334
void SetType(enum WifiMacType type)
Set Type/Subtype values with the correct values depending on the given type.
void SetAddress(Mac48Address ad)
Set MAC address of this MacLow.
Definition: mac-low.cc:549
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
WifiTxVector GetRtsTxVector(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
A base class which provides memory management and object aggregation.
Definition: object.h:87
tuple address
Definition: first.py:37
void ForwardDown(Ptr< const Packet > packet, const WifiMacHeader *hdr, WifiTxVector txVector, WifiPreamble preamble)
Forward the packet down to WifiPhy for transmission.
Definition: mac-low.cc:1641
PhyMacLowListener(ns3::MacLow *macLow)
Create a PhyMacLowListener for the given MacLow.
Definition: mac-low.cc:317
Time m_compressedBlockAckTimeout
Compressed block ACK timeout duration.
Definition: mac-low.h:1342
WifiMode GetMode(void) const
WifiTxVector GetBlockAckTxVector(Mac48Address address, WifiMode dataMode)
void ReceiveError(Ptr< Packet > packet, double rxSnr, bool isEndOfFrame)
Definition: mac-low.cc:842
bool MustWaitAck(void) const
Definition: mac-low.cc:208
bool IsRts(void) const
Return true if the header is a RTS header.
Headers for Block ack request.
Definition: ctrl-headers.h:50
bool IsAmpdu(Ptr< const Packet > packet, const WifiMacHeader hdr)
Checks if the given packet will be aggregated to an A-MPDU or not.
Definition: mac-low.cc:705
bool IsAck(void) const
Return true if the header is an ACK header.
void FlushAggregateQueue(void)
This function is called to flush the aggregate queue, which is used for A-MPDU.
Definition: mac-low.cc:3237
virtual ~PhyMacLowListener()
Definition: mac-low.cc:321
void ResetPhy(void)
Remove WifiPhy associated with this MacLow.
Definition: mac-low.cc:534
void DisableAck(void)
Do not wait for Ack after data transmission.
Definition: mac-low.cc:193
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:59
std::pair< BlockAckAgreement, std::list< BufferedPacket > > AgreementValue
Definition: mac-low.h:1364
virtual void NotifySwitchingStart(Time duration)
Definition: mac-low.cc:339
virtual Time GetLastRxStartTime(void) const =0
Return the start time of the last received packet.
WifiTxVector GetCtsTxVectorForRts(Mac48Address to, WifiMode rtsTxMode) const
Return a TXVECTOR for the CTS frame given the destination and the mode of the RTS used by the sender...
Definition: mac-low.cc:1418
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
Time GetBasicBlockAckTimeout() const
Return Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:639
a unique identifier for an interface.
Definition: type-id.h:58
WifiTxVector GetAckTxVector(Mac48Address address, WifiMode dataMode)
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:826
bool IsMultiTid(void) const
Check if the current ACK policy has multiple TID.
void SetQosAmsdu(void)
Set that A-MSDU is present.
Time m_rifs
Reduced Interframe Space (RIFS) duration.
Definition: mac-low.h:1347
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:36
WifiTxVector GetCtsTxVector(Mac48Address to, WifiMode rtsTxMode) const
Return a TXVECTOR for the CTS frame given the destination and the mode of the RTS used by the sender...
Definition: mac-low.cc:1400
uint8_t GetNoOfMpdus(void) const
Definition: ampdu-tag.cc:95
Introspection did not find any typical Config paths.
Definition: snr-tag.h:34
bool StoreMpduIfNeeded(Ptr< Packet > packet, WifiMacHeader hdr)
This method checks if exists a valid established block ack agreement.
Definition: mac-low.cc:2443
bool MustWaitNormalAck(void) const
Definition: mac-low.cc:213
virtual bool GetGreenfield(void) const =0
virtual ~MacLow()
Definition: mac-low.cc:383
A struct for packet, Wifi header, and timestamp.
Definition: mac-low.h:1302
Ptr< WifiPhy > m_phy
Pointer to WifiPhy (actually send/receives frames)
Definition: mac-low.h:1295
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:257
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
void SetCompressedBlockAckTimeout(Time blockAckTimeout)
Set Compressed Block ACK timeout of this MacLow.
Definition: mac-low.cc:567
Implements the IEEE 802.11 MAC trailer.
virtual void NotifyRxEndOk(void)
We have received the last bit of a packet for which NotifyRxStart was invoked first and...
Definition: mac-low.cc:327
virtual Ptr< MpduAggregator > GetMpduAggregator(void) const
Definition: mac-low.cc:120
void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > manager)
Set up WifiRemoteStationManager associated with this MacLow.
Definition: mac-low.cc:543
bool IsQosAck(void) const
Return if the QoS ACK policy is Normal ACK.
class PhyMacLowListener * m_phyMacLowListener
Listener needed to monitor when a channel switching occurs.
Definition: mac-low.h:1355
virtual uint32_t GetSerializedSize(void) const
mpduType
This enumeration defines the type of an MPDU.
Definition: wifi-phy.h:45
uint32_t GetSize(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return the total size of the packet after WifiMacHeader and FCS trailer have been added...
Definition: mac-low.cc:1363
MacLowTransmissionListener * m_listener
Transmission listener for the current packet.
Definition: mac-low.h:1337
void SetDsNotFrom(void)
Un-set the From DS bit in the Frame Control field.
void SendRtsForPacket(void)
Send RTS to begin RTS-CTS-DATA-ACK transaction.
Definition: mac-low.cc:1823
The MPDU is the last aggregate in an A-MPDU.
Definition: wifi-phy.h:52
void RxCompleteBufferedPacketsUntilFirstLost(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2593
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.