A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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_nTxMpdus (0)
372 {
373  NS_LOG_FUNCTION (this);
375  m_lastNavStart = Seconds (0);
376  m_promisc = false;
377  m_ampdu = false;
378  m_sentMpdus = 0;
379  m_aggregateQueue = CreateObject<WifiMacQueue> ();
380 }
381 
383 {
384  NS_LOG_FUNCTION (this);
385 }
386 
387 /* static */
388 TypeId
390 {
391  static TypeId tid = TypeId ("ns3::MacLow")
392  .SetParent<Object> ()
393  .SetGroupName ("Wifi")
394  .AddConstructor<MacLow> ()
395  ;
396  return tid;
397 }
398 
399 void
401 {
404 }
405 
406 void
408 {
409  if (m_phyMacLowListener != 0 )
410  {
412  delete m_phyMacLowListener;
414  }
415 }
416 
417 void
419 {
420  NS_LOG_FUNCTION (this);
433  m_phy = 0;
434  m_stationManager = 0;
435  if (m_phyMacLowListener != 0)
436  {
437  delete m_phyMacLowListener;
439  }
440  m_sentMpdus = 0;
441  m_aggregateQueue = 0;
442  m_ampdu = false;
443 }
444 
445 void
447 {
448  NS_LOG_FUNCTION (this);
449  bool oneRunning = false;
451  {
453  oneRunning = true;
454  }
456  {
458  oneRunning = true;
459  }
461  {
463  oneRunning = true;
464  }
466  {
468  oneRunning = true;
469  }
471  {
473  oneRunning = true;
474  }
476  {
478  oneRunning = true;
479  }
480  if (m_sendCtsEvent.IsRunning ())
481  {
483  oneRunning = true;
484  }
485  if (m_sendAckEvent.IsRunning ())
486  {
488  oneRunning = true;
489  }
490  if (m_sendDataEvent.IsRunning ())
491  {
493  oneRunning = true;
494  }
495  if (m_waitSifsEvent.IsRunning ())
496  {
498  oneRunning = true;
499  }
500  if (m_waitRifsEvent.IsRunning ())
501  {
503  oneRunning = true;
504  }
506  {
508  oneRunning = true;
509  }
510  if (oneRunning && m_listener != 0)
511  {
512  m_listener->Cancel ();
513  m_listener = 0;
514  }
515 }
516 
517 void
519 {
520  m_phy = phy;
524 }
525 
527 MacLow::GetPhy (void) const
528 {
529  return m_phy;
530 }
531 
532 void
534 {
538  m_phy = 0;
539 }
540 
541 void
543 {
544  m_stationManager = manager;
545 }
546 
547 void
549 {
550  m_self = ad;
551 }
552 
553 void
555 {
556  m_ackTimeout = ackTimeout;
557 }
558 
559 void
561 {
562  m_basicBlockAckTimeout = blockAckTimeout;
563 }
564 
565 void
567 {
568  m_compressedBlockAckTimeout = blockAckTimeout;
569 }
570 
571 void
573 {
574  m_ctsToSelfSupported = enable;
575 }
576 
577 bool
579 {
580  return m_ctsToSelfSupported;
581 }
582 
583 void
585 {
586  m_ctsTimeout = ctsTimeout;
587 }
588 
589 void
591 {
592  m_sifs = sifs;
593 }
594 
595 void
597 {
598  m_slotTime = slotTime;
599 }
600 
601 void
603 {
604  m_pifs = pifs;
605 }
606 
607 void
609 {
610  m_rifs = rifs;
611 }
612 
613 void
615 {
616  m_bssid = bssid;
617 }
618 
619 void
621 {
622  m_promisc = true;
623 }
624 
626 MacLow::GetAddress (void) const
627 {
628  return m_self;
629 }
630 
631 Time
633 {
634  return m_ackTimeout;
635 }
636 
637 Time
639 {
640  return m_basicBlockAckTimeout;
641 }
642 
643 Time
645 {
647 }
648 
649 Time
651 {
652  return m_ctsTimeout;
653 }
654 
655 Time
656 MacLow::GetSifs (void) const
657 {
658  return m_sifs;
659 }
660 
661 Time
662 MacLow::GetRifs (void) const
663 {
664  return m_rifs;
665 }
666 
667 Time
669 {
670  return m_slotTime;
671 }
672 
673 Time
674 MacLow::GetPifs (void) const
675 {
676  return m_pifs;
677 }
678 
680 MacLow::GetBssid (void) const
681 {
682  return m_bssid;
683 }
684 
685 bool
686 MacLow::IsPromisc (void) const
687 {
688  return m_promisc;
689 }
690 
691 void
693 {
694  m_rxCallback = callback;
695 }
696 
697 void
699 {
700  m_dcfListeners.push_back (listener);
701 }
702 
703 bool
705 {
706  uint32_t size, actualSize;
707  WifiMacTrailer fcs;
708  size = packet->GetSize () + hdr.GetSize () + fcs.GetSerializedSize ();
709  Ptr<Packet> p = AggregateToAmpdu (packet, hdr);
710  actualSize = p->GetSize ();
711  if (actualSize > size)
712  {
713  m_currentPacket = p;
714  return true;
715  }
716  else
717  {
718  return false;
719  }
720 }
721 
722 void
724  const WifiMacHeader* hdr,
726  MacLowTransmissionListener *listener)
727 {
728  NS_LOG_FUNCTION (this << packet << hdr << params << listener);
729  /* m_currentPacket is not NULL because someone started
730  * a transmission and was interrupted before one of:
731  * - ctsTimeout
732  * - sendDataAfterCTS
733  * expired. This means that one of these timers is still
734  * running. They are all cancelled below anyway by the
735  * call to CancelAllEvents (because of at least one
736  * of these two timers) which will trigger a call to the
737  * previous listener's cancel method.
738  *
739  * This typically happens because the high-priority
740  * QapScheduler has taken access to the channel from
741  * one of the Edca of the QAP.
742  */
743  m_currentPacket = packet->Copy ();
744  m_currentHdr = *hdr;
745  CancelAllEvents ();
746  m_listener = listener;
747  m_txParams = params;
749 
751  {
752  //This is mainly encountered when a higher priority control frame (such as beacons)
753  //is sent between A-MPDU transmissions. It avoids to unexpectedly flush the aggregate
754  //queue when previous RTS request has failed.
755  m_ampdu = false;
756  }
757  else if (m_aggregateQueue->GetSize () > 0)
758  {
759  //m_aggregateQueue > 0 occurs when a RTS/CTS exchange failed before an A-MPDU transmission.
760  //In that case, we transmit the same A-MPDU as previously.
761  m_sentMpdus = m_aggregateQueue->GetSize ();
762  m_ampdu = true;
763  if (m_sentMpdus > 1)
764  {
766  }
767  else if (m_currentHdr.IsQosData ())
768  {
769  //VHT single MPDUs are followed by normal ACKs
771  }
772  }
773  else
774  {
775  //Perform MPDU aggregation if possible
777  if (m_ampdu)
778  {
779  AmpduTag ampdu;
781  if (ampdu.GetRemainingNbOfMpdus () > 0)
782  {
784  }
785  else if (m_currentHdr.IsQosData ())
786  {
787  //VHT single MPDUs are followed by normal ACKs
789  }
790  }
791  }
792 
793  if (NeedRts ())
794  {
796  }
797  else
798  {
800  }
801 
802  NS_LOG_DEBUG ("startTx size=" << GetSize (m_currentPacket, &m_currentHdr) <<
803  ", to=" << m_currentHdr.GetAddr1 () << ", listener=" << m_listener);
804 
805  if (m_txParams.MustSendRts ())
806  {
807  SendRtsForPacket ();
808  }
809  else
810  {
812  {
813  SendCtsToSelf ();
814  }
815  else
816  {
817  SendDataPacket ();
818  }
819  }
820 
821  /* When this method completes, we have taken ownership of the medium. */
822  NS_ASSERT (m_phy->IsStateTx ());
823 }
824 
825 bool
827 {
830  m_currentPacket, dataTxVector);
831 }
832 
833 bool
835 {
837  return m_stationManager->NeedCtsToSelf (dataTxVector);
838 }
839 
840 void
841 MacLow::ReceiveError (Ptr<Packet> packet, double rxSnr)
842 {
843  NS_LOG_FUNCTION (this << packet << rxSnr);
844  NS_LOG_DEBUG ("rx failed ");
846  {
850  }
851  return;
852 }
853 
854 void
856 {
857  NS_LOG_DEBUG ("switching channel. Cancelling MAC pending events");
859  CancelAllEvents ();
861  {
863  }
866  m_currentPacket = 0;
867  m_listener = 0;
868 }
869 
870 void
872 {
873  NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
874  CancelAllEvents ();
876  {
878  }
881  m_currentPacket = 0;
882  m_listener = 0;
883 }
884 
885 void
886 MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, WifiPreamble preamble, bool ampduSubframe)
887 {
888  NS_LOG_FUNCTION (this << packet << rxSnr << txVector.GetMode () << preamble);
889  /* A packet is received from the PHY.
890  * When we have handled this packet,
891  * we handle any packet present in the
892  * packet queue.
893  */
894  WifiMacHeader hdr;
895  packet->RemoveHeader (hdr);
896  m_lastReceivedHdr = hdr;
897 
898  bool isPrevNavZero = IsNavZero ();
899  NS_LOG_DEBUG ("duration/id=" << hdr.GetDuration ());
900  NotifyNav (packet, hdr, preamble);
901  if (hdr.IsRts ())
902  {
903  /* see section 9.2.5.7 802.11-1999
904  * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS
905  * period if the NAV at the STA receiving the RTS frame indicates that the medium is
906  * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle,
907  * that STA shall not respond to the RTS frame.
908  */
909  if (ampduSubframe)
910  {
911  NS_FATAL_ERROR ("Received RTS as part of an A-MPDU");
912  }
913  else
914  {
915  if (isPrevNavZero
916  && hdr.GetAddr1 () == m_self)
917  {
918  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
920  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
921  rxSnr, txVector.GetMode ());
924  hdr.GetAddr2 (),
925  hdr.GetDuration (),
926  txVector,
927  rxSnr);
928  }
929  else
930  {
931  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
932  }
933  }
934  }
935  else if (hdr.IsCts ()
936  && hdr.GetAddr1 () == m_self
938  && m_currentPacket != 0)
939  {
940  if (ampduSubframe)
941  {
942  NS_FATAL_ERROR ("Received CTS as part of an A-MPDU");
943  }
944 
945  NS_LOG_DEBUG ("receive cts from=" << m_currentHdr.GetAddr1 ());
946 
947  SnrTag tag;
948  packet->RemovePacketTag (tag);
950  rxSnr, txVector.GetMode ());
952  rxSnr, txVector.GetMode (), tag.Get ());
953 
956  m_listener->GotCts (rxSnr, txVector.GetMode ());
960  hdr.GetAddr1 (),
961  hdr.GetDuration ());
962  }
963  else if (hdr.IsAck ()
964  && hdr.GetAddr1 () == m_self
968  && m_txParams.MustWaitAck ())
969  {
970  NS_LOG_DEBUG ("receive ack from=" << m_currentHdr.GetAddr1 ());
971  SnrTag tag;
972  packet->RemovePacketTag (tag);
974  rxSnr, txVector.GetMode ());
976  rxSnr, txVector.GetMode (), tag.Get ());
977 
979  m_ampdu = false;
980  bool gotAck = false;
981 
984  {
987  gotAck = true;
988  }
991  {
994  gotAck = true;
995  }
996  if (gotAck)
997  {
998  m_listener->GotAck (rxSnr, txVector.GetMode ());
999  }
1000  if (m_txParams.HasNextPacket ())
1001  {
1004  }
1005  }
1006  else if (hdr.IsBlockAck () && hdr.GetAddr1 () == m_self
1009  {
1010  NS_LOG_DEBUG ("got block ack from " << hdr.GetAddr2 ());
1011  SnrTag tag;
1012  packet->RemovePacketTag (tag);
1013  CtrlBAckResponseHeader blockAck;
1014  packet->RemoveHeader (blockAck);
1017  m_listener->GotBlockAck (&blockAck, hdr.GetAddr2 (), rxSnr, txVector.GetMode (), tag.Get ());
1018  m_sentMpdus = 0;
1019  m_ampdu = false;
1021  }
1022  else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
1023  {
1024  CtrlBAckRequestHeader blockAckReq;
1025  packet->RemoveHeader (blockAckReq);
1026  if (!blockAckReq.IsMultiTid ())
1027  {
1028  uint8_t tid = blockAckReq.GetTidInfo ();
1029  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), tid));
1030  if (it != m_bAckAgreements.end ())
1031  {
1032  //Update block ack cache
1033  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), tid));
1034  NS_ASSERT (i != m_bAckCaches.end ());
1035  (*i).second.UpdateWithBlockAckReq (blockAckReq.GetStartingSequence ());
1036 
1037  //NS_ASSERT (m_sendAckEvent.IsExpired ());
1039  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
1040  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
1041  if ((*it).second.first.IsImmediateBlockAck ())
1042  {
1043  NS_LOG_DEBUG ("rx blockAckRequest/sendImmediateBlockAck from=" << hdr.GetAddr2 ());
1046  blockAckReq,
1047  hdr.GetAddr2 (),
1048  hdr.GetDuration (),
1049  txVector.GetMode (),
1050  rxSnr);
1051  }
1052  else
1053  {
1054  NS_FATAL_ERROR ("Delayed block ack not supported.");
1055  }
1056  }
1057  else
1058  {
1059  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
1060  }
1061  }
1062  else
1063  {
1064  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
1065  }
1066  }
1067  else if (hdr.IsCtl ())
1068  {
1069  NS_LOG_DEBUG ("rx drop " << hdr.GetTypeString ());
1070  }
1071  else if (hdr.GetAddr1 () == m_self)
1072  {
1073  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
1074  rxSnr, txVector.GetMode ());
1075  if (hdr.IsQosData () && ReceiveMpdu (packet, hdr))
1076  {
1077  /* From section 9.10.4 in IEEE 802.11:
1078  Upon the receipt of a QoS data frame from the originator for which
1079  the Block Ack agreement exists, the recipient shall buffer the MSDU
1080  regardless of the value of the Ack Policy subfield within the
1081  QoS Control field of the QoS data frame. */
1082  if (hdr.IsQosAck () && !ampduSubframe)
1083  {
1084  NS_LOG_DEBUG ("rx QoS unicast/sendAck from=" << hdr.GetAddr2 ());
1085  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1086 
1087  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (),
1088  hdr.GetAddr2 (), hdr.GetQosTid ());
1089  RxCompleteBufferedPacketsUntilFirstLost (hdr.GetAddr2 (), hdr.GetQosTid ());
1092  &MacLow::SendAckAfterData, this,
1093  hdr.GetAddr2 (),
1094  hdr.GetDuration (),
1095  txVector.GetMode (),
1096  rxSnr);
1097  }
1098  else if (hdr.IsQosBlockAck ())
1099  {
1100  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1101  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
1102  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
1103  }
1104  return;
1105  }
1106  else if (hdr.IsQosData () && hdr.IsQosBlockAck ())
1107  {
1108  /* This happens if a packet with ack policy Block Ack is received and a block ack
1109  agreement for that packet doesn't exist.
1110 
1111  From section 11.5.3 in IEEE 802.11e:
1112  When a recipient does not have an active Block ack for a TID, but receives
1113  data MPDUs with the Ack Policy subfield set to Block Ack, it shall discard
1114  them and shall send a DELBA frame using the normal access
1115  mechanisms. */
1116  AcIndex ac = QosUtilsMapTidToAc (hdr.GetQosTid ());
1117  m_edcaListeners[ac]->BlockAckInactivityTimeout (hdr.GetAddr2 (), hdr.GetQosTid ());
1118  return;
1119  }
1120  else if (hdr.IsQosData () && hdr.IsQosNoAck ())
1121  {
1122  if (ampduSubframe)
1123  {
1124  NS_LOG_DEBUG ("rx Ampdu with No Ack Policy from=" << hdr.GetAddr2 ());
1125  }
1126  else
1127  {
1128  NS_LOG_DEBUG ("rx unicast/noAck from=" << hdr.GetAddr2 ());
1129  }
1130  }
1131  else if (hdr.IsData () || hdr.IsMgt ())
1132  {
1133  if (hdr.IsProbeResp ())
1134  {
1135  // Apply SNR tag for probe response quality measurements
1136  SnrTag tag;
1137  tag.Set (rxSnr);
1138  packet->AddPacketTag (tag);
1139  }
1140  if (hdr.IsMgt () && ampduSubframe)
1141  {
1142  NS_FATAL_ERROR ("Received management packet as part of an A-MPDU");
1143  }
1144  else
1145  {
1146  NS_LOG_DEBUG ("rx unicast/sendAck from=" << hdr.GetAddr2 ());
1149  &MacLow::SendAckAfterData, this,
1150  hdr.GetAddr2 (),
1151  hdr.GetDuration (),
1152  txVector.GetMode (),
1153  rxSnr);
1154  }
1155  }
1156  goto rxPacket;
1157  }
1158  else if (hdr.GetAddr1 ().IsGroup ())
1159  {
1160  if (ampduSubframe)
1161  {
1162  NS_FATAL_ERROR ("Received group addressed packet as part of an A-MPDU");
1163  }
1164  else
1165  {
1166  if (hdr.IsData () || hdr.IsMgt ())
1167  {
1168  NS_LOG_DEBUG ("rx group from=" << hdr.GetAddr2 ());
1169  if (hdr.IsBeacon ())
1170  {
1171  // Apply SNR tag for beacon quality measurements
1172  SnrTag tag;
1173  tag.Set (rxSnr);
1174  packet->AddPacketTag (tag);
1175  }
1176  goto rxPacket;
1177  }
1178  else
1179  {
1180  // DROP
1181  }
1182  }
1183  }
1184  else if (m_promisc)
1185  {
1186  NS_ASSERT (hdr.GetAddr1 () != m_self);
1187  if (hdr.IsData ())
1188  {
1189  goto rxPacket;
1190  }
1191  }
1192  else
1193  {
1194  //NS_LOG_DEBUG_VERBOSE ("rx not-for-me from %d", GetSource (packet));
1195  }
1196  return;
1197 rxPacket:
1198  WifiMacTrailer fcs;
1199  packet->RemoveTrailer (fcs);
1200  m_rxCallback (packet, &hdr);
1201  return;
1202 }
1203 
1204 uint8_t
1206 {
1207  uint8_t tid = 0;
1208  if (hdr.IsQosData ())
1209  {
1210  tid = hdr.GetQosTid ();
1211  }
1212  else if (hdr.IsBlockAckReq ())
1213  {
1214  CtrlBAckRequestHeader baReqHdr;
1215  packet->PeekHeader (baReqHdr);
1216  tid = baReqHdr.GetTidInfo ();
1217  }
1218  else if (hdr.IsBlockAck ())
1219  {
1220  CtrlBAckResponseHeader baRespHdr;
1221  packet->PeekHeader (baRespHdr);
1222  tid = baRespHdr.GetTidInfo ();
1223  }
1224  return tid;
1225 }
1226 
1227 uint32_t
1229 {
1230  WifiMacHeader ack;
1231  ack.SetType (WIFI_MAC_CTL_ACK);
1232  return ack.GetSize () + 4;
1233 }
1234 
1235 uint32_t
1237 {
1238  WifiMacHeader hdr;
1240  CtrlBAckResponseHeader blockAck;
1241  if (type == BASIC_BLOCK_ACK)
1242  {
1243  blockAck.SetType (BASIC_BLOCK_ACK);
1244  }
1245  else if (type == COMPRESSED_BLOCK_ACK)
1246  {
1247  blockAck.SetType (COMPRESSED_BLOCK_ACK);
1248  }
1249  else if (type == MULTI_TID_BLOCK_ACK)
1250  {
1251  //Not implemented
1252  NS_ASSERT (false);
1253  }
1254  return hdr.GetSize () + blockAck.GetSerializedSize () + 4;
1255 }
1256 
1257 uint32_t
1259 {
1260  WifiMacHeader rts;
1261  rts.SetType (WIFI_MAC_CTL_RTS);
1262  return rts.GetSize () + 4;
1263 }
1264 
1265 Time
1267 {
1268  WifiTxVector ackTxVector = GetAckTxVectorForData (to, dataTxVector.GetMode ());
1269  return GetAckDuration (ackTxVector);
1270 }
1271 
1272 Time
1274 {
1275  NS_ASSERT (ackTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
1276  WifiPreamble preamble;
1278  {
1279  preamble = WIFI_PREAMBLE_SHORT;
1280  }
1281  else
1282  {
1283  preamble = WIFI_PREAMBLE_LONG;
1284  }
1285  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, preamble, m_phy->GetFrequency ());
1286 }
1287 
1288 Time
1289 MacLow::GetBlockAckDuration (Mac48Address to, WifiTxVector blockAckReqTxVector, enum BlockAckType type) const
1290 {
1291  /*
1292  * For immediate Basic BlockAck we should transmit the frame with the same WifiMode
1293  * as the BlockAckReq.
1294  */
1295  WifiPreamble preamble;
1296  if (blockAckReqTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT && type == BASIC_BLOCK_ACK)
1297  {
1298  preamble = WIFI_PREAMBLE_HT_MF;
1299  }
1301  {
1302  preamble = WIFI_PREAMBLE_SHORT;
1303  }
1304  else
1305  {
1306  preamble = WIFI_PREAMBLE_LONG;
1307  }
1308  return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, preamble, m_phy->GetFrequency ());
1309 }
1310 
1311 Time
1313 {
1314  WifiTxVector ctsTxVector = GetCtsTxVectorForRts (to, rtsTxVector.GetMode ());
1315  return GetCtsDuration (ctsTxVector);
1316 }
1317 
1318 Time
1320 {
1321  NS_ASSERT (ctsTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1322  WifiPreamble preamble;
1324  {
1325  preamble = WIFI_PREAMBLE_SHORT;
1326  }
1327  else
1328  {
1329  preamble = WIFI_PREAMBLE_LONG;
1330  }
1331  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency ());
1332 }
1333 
1334 uint32_t
1336 {
1337  WifiMacHeader cts;
1338  cts.SetType (WIFI_MAC_CTL_CTS);
1339  return cts.GetSize () + 4;
1340 }
1341 
1342 uint32_t
1344 {
1345  uint32_t size;
1346  WifiMacTrailer fcs;
1347  if (m_ampdu)
1348  {
1349  size = packet->GetSize ();
1350  }
1351  else
1352  {
1353  size = packet->GetSize () + hdr->GetSize () + fcs.GetSerializedSize ();
1354  }
1355  return size;
1356 }
1357 
1360 {
1361  return m_stationManager->GetCtsToSelfTxVector (hdr, packet);
1362 }
1363 
1366 {
1367  Mac48Address to = hdr->GetAddr1 ();
1368  return m_stationManager->GetRtsTxVector (to, hdr, packet);
1369 }
1370 
1373 {
1374  Mac48Address to = hdr->GetAddr1 ();
1375  WifiMacTrailer fcs;
1376  return m_stationManager->GetDataTxVector (to, hdr, packet);
1377 }
1378 
1381 {
1382  return m_stationManager->GetCtsTxVector (to, rtsTxMode);
1383 }
1384 
1387 {
1388  return m_stationManager->GetAckTxVector (to, dataTxMode);
1389 }
1390 
1393 {
1394  return m_stationManager->GetBlockAckTxVector (to, dataTxMode);
1395 }
1396 
1399 {
1400  return GetCtsTxVector (to, rtsTxMode);
1401 }
1402 
1405 {
1406  return GetAckTxVector (to, dataTxMode);
1407 }
1408 
1409 Time
1411  const WifiMacHeader* hdr,
1412  const MacLowTransmissionParameters& params) const
1413 {
1414  WifiPreamble preamble;
1415  Time txTime = Seconds (0);
1416  if (params.MustSendRts ())
1417  {
1418  WifiTxVector rtsTxVector = GetRtsTxVector (packet, hdr);
1419  //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
1421  {
1422  preamble = WIFI_PREAMBLE_HT_GF;
1423  }
1424  //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1426  {
1427  preamble = WIFI_PREAMBLE_SHORT;
1428  }
1429  else
1430  {
1431  preamble = WIFI_PREAMBLE_LONG;
1432  }
1433  txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency ());
1434  txTime += GetCtsDuration (hdr->GetAddr1 (), rtsTxVector);
1435  txTime += Time (GetSifs () * 2);
1436  }
1437  WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
1438  if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_VHT)
1439  {
1440  preamble = WIFI_PREAMBLE_VHT;
1441  }
1443  {
1444  preamble = WIFI_PREAMBLE_HT_GF;
1445  }
1446  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1447  {
1448  preamble = WIFI_PREAMBLE_HT_MF;
1449  }
1451  {
1452  preamble = WIFI_PREAMBLE_SHORT;
1453  }
1454  else
1455  {
1456  preamble = WIFI_PREAMBLE_LONG;
1457  }
1458  uint32_t dataSize = GetSize (packet, hdr);
1459  txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, preamble, m_phy->GetFrequency ());
1460  if (params.MustWaitAck ())
1461  {
1462  txTime += GetSifs ();
1463  txTime += GetAckDuration (hdr->GetAddr1 (), dataTxVector);
1464  }
1465  return txTime;
1466 }
1467 
1468 Time
1470  const WifiMacHeader* hdr,
1471  const MacLowTransmissionParameters& params) const
1472 {
1473  Time txTime = CalculateOverallTxTime (packet, hdr, params);
1474  if (params.HasNextPacket ())
1475  {
1476  WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
1477  WifiPreamble preamble;
1478  if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1479  {
1480  preamble = WIFI_PREAMBLE_VHT;
1481  }
1483  {
1484  preamble = WIFI_PREAMBLE_HT_GF;
1485  }
1486  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1487  {
1488  preamble = WIFI_PREAMBLE_HT_MF;
1489  }
1491  {
1492  preamble = WIFI_PREAMBLE_SHORT;
1493  }
1494  else
1495  {
1496  preamble = WIFI_PREAMBLE_LONG;
1497  }
1498  txTime += GetSifs ();
1499  txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, preamble, m_phy->GetFrequency ());
1500  }
1501  return txTime;
1502 }
1503 
1504 void
1506 {
1508  Time duration = hdr.GetDuration ();
1509 
1510  if (hdr.IsCfpoll ()
1511  && hdr.GetAddr2 () == m_bssid)
1512  {
1513  //see section 9.3.2.2 802.11-1999
1514  DoNavResetNow (duration);
1515  return;
1516  }
1519  else if (hdr.GetAddr1 () != m_self)
1520  {
1521  // see section 9.2.5.4 802.11-1999
1522  bool navUpdated = DoNavStartNow (duration);
1523  if (hdr.IsRts () && navUpdated)
1524  {
1533  WifiMacHeader cts;
1534  cts.SetType (WIFI_MAC_CTL_CTS);
1535  WifiTxVector txVector = GetRtsTxVector (packet, &hdr);
1536  Time navCounterResetCtsMissedDelay =
1537  m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, preamble, m_phy->GetFrequency ()) +
1538  Time (2 * GetSifs ()) + Time (2 * GetSlotTime ());
1539  m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
1541  Simulator::Now ());
1542  }
1543  }
1544 }
1545 
1546 void
1548 {
1549  if (m_phy->GetLastRxStartTime () < rtsEndRxTime)
1550  {
1551  DoNavResetNow (Seconds (0.0));
1552  }
1553 }
1554 
1555 void
1557 {
1558  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1559  {
1560  (*i)->NavReset (duration);
1561  }
1563  m_lastNavDuration = duration;
1564 }
1565 
1566 bool
1568 {
1569  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1570  {
1571  (*i)->NavStart (duration);
1572  }
1573  Time newNavEnd = Simulator::Now () + duration;
1574  Time oldNavEnd = m_lastNavStart + m_lastNavDuration;
1575  if (newNavEnd > oldNavEnd)
1576  {
1578  m_lastNavDuration = duration;
1579  return true;
1580  }
1581  return false;
1582 }
1583 
1584 void
1586 {
1587  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1588  {
1589  (*i)->AckTimeoutStart (duration);
1590  }
1591 }
1592 
1593 void
1595 {
1596  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1597  {
1598  (*i)->AckTimeoutReset ();
1599  }
1600 }
1601 
1602 void
1604 {
1605  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1606  {
1607  (*i)->CtsTimeoutStart (duration);
1608  }
1609 }
1610 
1611 void
1613 {
1614  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1615  {
1616  (*i)->CtsTimeoutReset ();
1617  }
1618 }
1619 
1620 void
1622  WifiTxVector txVector, WifiPreamble preamble)
1623 {
1624  NS_LOG_FUNCTION (this << packet << hdr << txVector);
1625  NS_LOG_DEBUG ("send " << hdr->GetTypeString () <<
1626  ", to=" << hdr->GetAddr1 () <<
1627  ", size=" << packet->GetSize () <<
1628  ", mode=" << txVector.GetMode () <<
1629  ", duration=" << hdr->GetDuration () <<
1630  ", seq=0x" << std::hex << m_currentHdr.GetSequenceControl () << std::dec);
1631  if (!m_ampdu || hdr->IsRts () || hdr->IsBlockAck ())
1632  {
1633  m_phy->SendPacket (packet, txVector, preamble);
1634  }
1635  else
1636  {
1637  Ptr<Packet> newPacket;
1638  Ptr <const Packet> dequeuedPacket;
1639  WifiMacHeader newHdr;
1640  WifiMacTrailer fcs;
1641  m_nTxMpdus = m_aggregateQueue->GetSize ();
1642  uint32_t queueSize = m_aggregateQueue->GetSize ();
1643  bool vhtSingleMpdu = false;
1644  bool last = false;
1645  enum mpduType mpdutype = NORMAL_MPDU;
1646 
1647  uint8_t tid = GetTid (packet, *hdr);
1648  AcIndex ac = QosUtilsMapTidToAc (tid);
1649  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt = m_edcaListeners.find (ac);
1650 
1651  if (queueSize == 1)
1652  {
1653  vhtSingleMpdu = true;
1654  }
1655 
1656  //Add packet tag
1657  AmpduTag ampdutag;
1658  ampdutag.SetAmpdu (true);
1659  Time delay = Seconds (0);
1660  Time remainingAmpduDuration = m_phy->CalculateTxDuration (packet->GetSize (), txVector, preamble, m_phy->GetFrequency ());
1661  if (queueSize > 1 || vhtSingleMpdu)
1662  {
1663  txVector.SetAggregation (true);
1664  }
1665  for (; queueSize > 0; queueSize--)
1666  {
1667  dequeuedPacket = m_aggregateQueue->Dequeue (&newHdr);
1668  newPacket = dequeuedPacket->Copy ();
1669  newHdr.SetDuration (hdr->GetDuration ());
1670  newPacket->AddHeader (newHdr);
1671  newPacket->AddTrailer (fcs);
1672  if (queueSize == 1)
1673  {
1674  last = true;
1675  mpdutype = LAST_MPDU_IN_AGGREGATE;
1676  }
1677 
1678  listenerIt->second->GetMpduAggregator ()->AddHeaderAndPad (newPacket, last, vhtSingleMpdu);
1679 
1680  if (delay == Seconds (0))
1681  {
1682  if (!vhtSingleMpdu)
1683  {
1684  NS_LOG_DEBUG ("Sending MPDU as part of A-MPDU");
1685  mpdutype = MPDU_IN_AGGREGATE;
1686  }
1687  else
1688  {
1689  mpdutype = NORMAL_MPDU;
1690  }
1691  }
1692 
1693  Time mpduDuration = m_phy->CalculateTxDuration (newPacket->GetSize (), txVector, preamble, m_phy->GetFrequency (), mpdutype, 0);
1694  remainingAmpduDuration -= mpduDuration;
1695 
1696  ampdutag.SetRemainingNbOfMpdus (queueSize - 1);
1697  if (queueSize > 1)
1698  {
1699  ampdutag.SetRemainingAmpduDuration (remainingAmpduDuration);
1700  }
1701  else
1702  {
1703  ampdutag.SetRemainingAmpduDuration (NanoSeconds (0));
1704  }
1705  newPacket->AddPacketTag (ampdutag);
1706 
1707  if (delay == Seconds (0))
1708  {
1709  m_phy->SendPacket (newPacket, txVector, preamble, mpdutype);
1710  }
1711  else
1712  {
1713  Simulator::Schedule (delay, &MacLow::SendMpdu, this, newPacket, txVector, preamble, mpdutype);
1714  }
1715  if (queueSize > 1)
1716  {
1717  NS_ASSERT (remainingAmpduDuration > 0);
1718  delay = delay + mpduDuration;
1719  }
1720 
1721  preamble = WIFI_PREAMBLE_NONE;
1722  }
1723  }
1724 }
1725 
1726 void
1727 MacLow::SendMpdu (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, enum mpduType mpdutype)
1728 {
1729  NS_LOG_DEBUG ("Sending MPDU as part of A-MPDU");
1730  m_phy->SendPacket (packet, txVector, preamble, mpdutype);
1731 }
1732 
1733 void
1735 {
1736  NS_LOG_FUNCTION (this);
1737  NS_LOG_DEBUG ("cts timeout");
1742  if (m_sentMpdus == 0)
1743  {
1744  m_currentPacket = 0;
1745  }
1747  m_listener = 0;
1748  m_sentMpdus = 0;
1749  m_ampdu = false;
1750  listener->MissedCts ();
1751 }
1752 
1753 void
1755 {
1756  NS_LOG_FUNCTION (this);
1757  NS_LOG_DEBUG ("normal ack timeout");
1763  m_listener = 0;
1764  m_sentMpdus = 0;
1765  m_ampdu = false;
1767  listener->MissedAck ();
1768 }
1769 
1770 void
1772 {
1773  NS_LOG_FUNCTION (this);
1776  m_listener = 0;
1777  if (m_phy->IsStateIdle ())
1778  {
1779  NS_LOG_DEBUG ("fast Ack idle missed");
1780  listener->MissedAck ();
1781  }
1782  else
1783  {
1784  NS_LOG_DEBUG ("fast Ack ok");
1785  }
1786 }
1787 
1788 void
1790 {
1791  NS_LOG_FUNCTION (this);
1792  NS_LOG_DEBUG ("block ack timeout");
1794  m_listener = 0;
1795  m_sentMpdus = 0;
1796  m_ampdu = false;
1798  listener->MissedBlockAck (m_nTxMpdus);
1799 }
1800 
1801 void
1803 {
1804  NS_LOG_FUNCTION (this);
1807  m_listener = 0;
1808  if (m_phy->IsStateIdle ())
1809  {
1810  NS_LOG_DEBUG ("super fast Ack failed");
1811  listener->MissedAck ();
1812  }
1813  else
1814  {
1815  NS_LOG_DEBUG ("super fast Ack ok");
1816  listener->GotAck (0.0, WifiMode ());
1817  }
1818 }
1819 
1820 void
1822 {
1823  NS_LOG_FUNCTION (this);
1824  /* send an RTS for this packet. */
1825  WifiMacHeader rts;
1826  rts.SetType (WIFI_MAC_CTL_RTS);
1827  rts.SetDsNotFrom ();
1828  rts.SetDsNotTo ();
1829  rts.SetNoRetry ();
1830  rts.SetNoMoreFragments ();
1831  rts.SetAddr1 (m_currentHdr.GetAddr1 ());
1832  rts.SetAddr2 (m_self);
1834  Time duration = Seconds (0);
1835 
1836  WifiPreamble preamble;
1837  //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
1839  {
1840  preamble = WIFI_PREAMBLE_HT_GF;
1841  }
1842  //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1844  {
1845  preamble = WIFI_PREAMBLE_SHORT;
1846  }
1847  else
1848  {
1849  preamble = WIFI_PREAMBLE_LONG;
1850  }
1851 
1852  if (m_txParams.HasDurationId ())
1853  {
1854  duration += m_txParams.GetDurationId ();
1855  }
1856  else
1857  {
1858  duration += GetSifs ();
1859  duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxVector);
1860  duration += GetSifs ();
1862  m_currentTxVector, preamble, m_phy->GetFrequency ());
1863  duration += GetSifs ();
1865  {
1867  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
1868  }
1870  {
1872  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1873  }
1874  else if (m_txParams.MustWaitAck ())
1875  {
1877  }
1878  if (m_txParams.HasNextPacket ())
1879  {
1881  m_currentTxVector, preamble, m_phy->GetFrequency ());
1882  if (m_txParams.MustWaitAck ())
1883  {
1884  duration += GetSifs ();
1886  }
1887  }
1888  }
1889  rts.SetDuration (duration);
1890 
1891  Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency ());
1892  Time timerDelay = txDuration + GetCtsTimeout ();
1893 
1895  NotifyCtsTimeoutStartNow (timerDelay);
1897 
1898  Ptr<Packet> packet = Create<Packet> ();
1899  packet->AddHeader (rts);
1900  WifiMacTrailer fcs;
1901  packet->AddTrailer (fcs);
1902 
1903  ForwardDown (packet, &rts, rtsTxVector, preamble);
1904 }
1905 
1906 void
1908 {
1909  WifiPreamble preamble;
1910 
1911  if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_VHT)
1912  {
1913  preamble = WIFI_PREAMBLE_VHT;
1914  }
1915  //Since it is data then it can have format = GF
1917  {
1918  preamble = WIFI_PREAMBLE_HT_GF;
1919  }
1920  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1921  {
1922  preamble = WIFI_PREAMBLE_HT_MF;
1923  }
1925  {
1926  preamble = WIFI_PREAMBLE_SHORT;
1927  }
1928  else
1929  {
1930  preamble = WIFI_PREAMBLE_LONG;
1931  }
1932 
1933  Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), dataTxVector, preamble, m_phy->GetFrequency ());
1935  {
1936  Time timerDelay = txDuration + GetAckTimeout ();
1938  NotifyAckTimeoutStartNow (timerDelay);
1940  }
1941  else if (m_txParams.MustWaitFastAck ())
1942  {
1943  Time timerDelay = txDuration + GetPifs ();
1945  NotifyAckTimeoutStartNow (timerDelay);
1947  }
1948  else if (m_txParams.MustWaitSuperFastAck ())
1949  {
1950  Time timerDelay = txDuration + GetPifs ();
1952  NotifyAckTimeoutStartNow (timerDelay);
1955  }
1956  else if (m_txParams.MustWaitBasicBlockAck ())
1957  {
1958  Time timerDelay = txDuration + GetBasicBlockAckTimeout ();
1960  NotifyAckTimeoutStartNow (timerDelay);
1962  }
1964  {
1965  Time timerDelay = txDuration + GetCompressedBlockAckTimeout ();
1967  NotifyAckTimeoutStartNow (timerDelay);
1969  }
1970  else if (m_txParams.HasNextPacket ())
1971  {
1973  {
1974  Time delay = txDuration + GetRifs ();
1977  }
1978  else
1979  {
1980  Time delay = txDuration + GetSifs ();
1983  }
1984  }
1985  else
1986  {
1987  // since we do not expect any timer to be triggered.
1988  Simulator::Schedule (txDuration, &MacLow::EndTxNoAck, this);
1989  }
1990 }
1991 
1992 void
1994 {
1995  NS_LOG_FUNCTION (this);
1996  /* send this packet directly. No RTS is needed. */
1997  WifiPreamble preamble;
1999  {
2000  preamble = WIFI_PREAMBLE_VHT;
2001  }
2003  {
2004  //In the future has to make sure that receiver has greenfield enabled
2005  preamble = WIFI_PREAMBLE_HT_GF;
2006  }
2008  {
2009  preamble = WIFI_PREAMBLE_HT_MF;
2010  }
2012  {
2013  preamble = WIFI_PREAMBLE_SHORT;
2014  }
2015  else
2016  {
2017  preamble = WIFI_PREAMBLE_LONG;
2018  }
2019 
2021 
2022  Time duration = Seconds (0.0);
2023  if (m_txParams.HasDurationId ())
2024  {
2025  duration += m_txParams.GetDurationId ();
2026  }
2027  else
2028  {
2030  {
2031  duration += GetSifs ();
2033  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
2034  }
2036  {
2037  duration += GetSifs ();
2039  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2040  }
2041  else if (m_txParams.MustWaitAck ())
2042  {
2043  duration += GetSifs ();
2045  }
2046  if (m_txParams.HasNextPacket ())
2047  {
2048  duration += GetSifs ();
2050  m_currentTxVector, preamble, m_phy->GetFrequency ());
2051  if (m_txParams.MustWaitAck ())
2052  {
2053  duration += GetSifs ();
2055  }
2056  }
2057  }
2058  m_currentHdr.SetDuration (duration);
2059 
2060  if (!m_ampdu)
2061  {
2063  WifiMacTrailer fcs;
2064  m_currentPacket->AddTrailer (fcs);
2065  }
2066 
2068  m_currentPacket = 0;
2069 }
2070 
2071 bool
2072 MacLow::IsNavZero (void) const
2073 {
2075  {
2076  return true;
2077  }
2078  else
2079  {
2080  return false;
2081  }
2082 }
2083 
2084 void
2086 {
2087  WifiMacHeader cts;
2088  cts.SetType (WIFI_MAC_CTL_CTS);
2089  cts.SetDsNotFrom ();
2090  cts.SetDsNotTo ();
2091  cts.SetNoMoreFragments ();
2092  cts.SetNoRetry ();
2093  cts.SetAddr1 (m_self);
2094 
2096 
2097  WifiPreamble preamble;
2098  if (ctsTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
2099  {
2100  preamble = WIFI_PREAMBLE_HT_MF;
2101  }
2103  {
2104  preamble = WIFI_PREAMBLE_SHORT;
2105  }
2106  else
2107  {
2108  preamble = WIFI_PREAMBLE_LONG;
2109  }
2110 
2111  Time duration = Seconds (0);
2112 
2113  if (m_txParams.HasDurationId ())
2114  {
2115  duration += m_txParams.GetDurationId ();
2116  }
2117  else
2118  {
2119  duration += GetSifs ();
2121  m_currentTxVector, preamble, m_phy->GetFrequency ());
2123  {
2124 
2125  duration += GetSifs ();
2127  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
2128  }
2130  {
2131  duration += GetSifs ();
2133  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2134  }
2135  else if (m_txParams.MustWaitAck ())
2136  {
2137  duration += GetSifs ();
2139  }
2140  if (m_txParams.HasNextPacket ())
2141  {
2142  duration += GetSifs ();
2144  m_currentTxVector, preamble, m_phy->GetFrequency ());
2146  {
2147  duration += GetSifs ();
2149  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2150  }
2151  else if (m_txParams.MustWaitAck ())
2152  {
2153  duration += GetSifs ();
2155  }
2156  }
2157  }
2158 
2159  cts.SetDuration (duration);
2160 
2161  Ptr<Packet> packet = Create<Packet> ();
2162  packet->AddHeader (cts);
2163  WifiMacTrailer fcs;
2164  packet->AddTrailer (fcs);
2165 
2166  ForwardDown (packet, &cts, ctsTxVector,preamble);
2167 
2168  Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency ());
2169  txDuration += GetSifs ();
2171 
2172  m_sendDataEvent = Simulator::Schedule (txDuration,
2173  &MacLow::SendDataAfterCts, this,
2174  cts.GetAddr1 (),
2175  duration);
2176 
2177 }
2178 
2179 void
2180 MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
2181 {
2182  NS_LOG_FUNCTION (this << source << duration << rtsTxVector.GetMode () << rtsSnr);
2183  /* send a CTS when you receive a RTS
2184  * right after SIFS.
2185  */
2186  WifiTxVector ctsTxVector = GetCtsTxVector (source, rtsTxVector.GetMode ());
2187  WifiMacHeader cts;
2188  cts.SetType (WIFI_MAC_CTL_CTS);
2189  cts.SetDsNotFrom ();
2190  cts.SetDsNotTo ();
2191  cts.SetNoMoreFragments ();
2192  cts.SetNoRetry ();
2193  cts.SetAddr1 (source);
2194  duration -= GetCtsDuration (source, rtsTxVector);
2195  duration -= GetSifs ();
2196  NS_ASSERT (duration >= MicroSeconds (0));
2197  cts.SetDuration (duration);
2198 
2199  Ptr<Packet> packet = Create<Packet> ();
2200  packet->AddHeader (cts);
2201  WifiMacTrailer fcs;
2202  packet->AddTrailer (fcs);
2203 
2204  SnrTag tag;
2205  tag.Set (rtsSnr);
2206  packet->AddPacketTag (tag);
2207 
2208  WifiPreamble preamble;
2210  {
2211  preamble = WIFI_PREAMBLE_SHORT;
2212  }
2213  else
2214  {
2215  preamble = WIFI_PREAMBLE_LONG;
2216  }
2217 
2218  //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
2219  ForwardDown (packet, &cts, ctsTxVector, preamble);
2220 }
2221 
2222 void
2224 {
2225  NS_LOG_FUNCTION (this);
2226  /* send the third step in a
2227  * RTS/CTS/DATA/ACK hanshake
2228  */
2229  NS_ASSERT (m_currentPacket != 0);
2230 
2231  if (m_aggregateQueue->GetSize () != 0)
2232  {
2233  for (std::vector<Item>::size_type i = 0; i != m_txPackets.size (); i++)
2234  {
2235  uint8_t tid = GetTid (m_txPackets.at (i).packet, m_txPackets.at (i).hdr);
2236  AcIndex ac = QosUtilsMapTidToAc (tid);
2237  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt = m_edcaListeners.find (ac);
2238 
2239  listenerIt->second->CompleteMpduTx (m_txPackets.at (i).packet, m_txPackets.at (i).hdr, m_txPackets.at (i).timestamp);
2240  }
2241  m_txPackets.clear ();
2242  }
2243 
2244  WifiPreamble preamble;
2246  {
2247  preamble = WIFI_PREAMBLE_VHT;
2248  }
2250  {
2251  //In the future has to make sure that receiver has greenfield enabled
2252  preamble = WIFI_PREAMBLE_HT_GF;
2253  }
2255  {
2256  preamble = WIFI_PREAMBLE_HT_MF;
2257  }
2259  {
2260  preamble = WIFI_PREAMBLE_SHORT;
2261  }
2262  else
2263  {
2264  preamble = WIFI_PREAMBLE_LONG;
2265  }
2266 
2268  Time newDuration = Seconds (0);
2270  {
2271  newDuration += GetSifs ();
2273  newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
2274  }
2276  {
2277  newDuration += GetSifs ();
2279  newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2280  }
2281  else if (m_txParams.MustWaitAck ())
2282  {
2283  newDuration += GetSifs ();
2285  }
2286  if (m_txParams.HasNextPacket ())
2287  {
2288  newDuration += GetSifs ();
2291  {
2292  newDuration += GetSifs ();
2294  newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2295  }
2296  else if (m_txParams.MustWaitAck ())
2297  {
2298  newDuration += GetSifs ();
2300  }
2301  }
2302 
2304  duration -= txDuration;
2305  duration -= GetSifs ();
2306 
2307  duration = std::max (duration, newDuration);
2308  NS_ASSERT (duration >= MicroSeconds (0));
2309  m_currentHdr.SetDuration (duration);
2310 
2311  if (!m_ampdu)
2312  {
2314  WifiMacTrailer fcs;
2315  m_currentPacket->AddTrailer (fcs);
2316  }
2317 
2319  m_currentPacket = 0;
2320 }
2321 
2322 void
2324 {
2325  m_listener->StartNext ();
2326 }
2327 
2328 void
2330 {
2332  m_listener = 0;
2333  listener->EndTxNoAck ();
2334 }
2335 
2336 void
2338 {
2339  NS_LOG_FUNCTION (this);
2341  m_listener = 0;
2342  listener->MissedAck ();
2343  NS_LOG_DEBUG ("fast Ack busy but missed");
2344 }
2345 
2346 void
2347 MacLow::SendAckAfterData (Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
2348 {
2349  NS_LOG_FUNCTION (this);
2350  // send an ACK, after SIFS, when you receive a packet
2351  WifiTxVector ackTxVector = GetAckTxVector (source, dataTxMode);
2352  WifiMacHeader ack;
2353  ack.SetType (WIFI_MAC_CTL_ACK);
2354  ack.SetDsNotFrom ();
2355  ack.SetDsNotTo ();
2356  ack.SetNoRetry ();
2357  ack.SetNoMoreFragments ();
2358  ack.SetAddr1 (source);
2359  // 802.11-2012, Section 8.3.1.4: Duration/ID is received duration value
2360  // minus the time to transmit the ACK frame and its SIFS interval
2361  duration -= GetAckDuration (ackTxVector);
2362  duration -= GetSifs ();
2363  NS_ASSERT_MSG (duration >= MicroSeconds (0), "Please provide test case to maintainers if this assert is hit.");
2364  ack.SetDuration (duration);
2365 
2366  Ptr<Packet> packet = Create<Packet> ();
2367  packet->AddHeader (ack);
2368  WifiMacTrailer fcs;
2369  packet->AddTrailer (fcs);
2370 
2371  SnrTag tag;
2372  tag.Set (dataSnr);
2373  packet->AddPacketTag (tag);
2374 
2375  WifiPreamble preamble;
2377  {
2378  preamble = WIFI_PREAMBLE_SHORT;
2379  }
2380  else
2381  {
2382  preamble = WIFI_PREAMBLE_LONG;
2383  }
2384 
2385  //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
2386  ForwardDown (packet, &ack, ackTxVector, preamble);
2387 }
2388 
2389 bool
2390 MacLow::IsInWindow (uint16_t seq, uint16_t winstart, uint16_t winsize)
2391 {
2392  return ((seq - winstart + 4096) % 4096) < winsize;
2393 }
2394 
2395 bool
2397 {
2399  {
2400  Mac48Address originator = hdr.GetAddr2 ();
2401  uint8_t tid = 0;
2402  if (hdr.IsQosData ())
2403  {
2404  tid = hdr.GetQosTid ();
2405  }
2406  uint16_t seqNumber = hdr.GetSequenceNumber ();
2407  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2408  if (it != m_bAckAgreements.end ())
2409  {
2410  //Implement HT immediate Block Ack support for HT Delayed Block Ack is not added yet
2411  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), seqNumber))
2412  {
2413  StoreMpduIfNeeded (packet, hdr);
2414  if (!IsInWindow (hdr.GetSequenceNumber (), (*it).second.first.GetStartingSequence (), (*it).second.first.GetBufferSize ()))
2415  {
2416  uint16_t delta = (seqNumber - (*it).second.first.GetWinEnd () + 4096) % 4096;
2417  if (delta > 1)
2418  {
2419  (*it).second.first.SetWinEnd (seqNumber);
2420  int16_t winEnd = (*it).second.first.GetWinEnd ();
2421  int16_t bufferSize = (*it).second.first.GetBufferSize ();
2422  uint16_t sum = ((uint16_t)(std::abs (winEnd - bufferSize + 1))) % 4096;
2423  (*it).second.first.SetStartingSequence (sum);
2424  RxCompleteBufferedPacketsWithSmallerSequence ((*it).second.first.GetStartingSequenceControl (), originator, tid);
2425  }
2426  }
2427  RxCompleteBufferedPacketsUntilFirstLost (originator, tid); //forwards up packets starting from winstart and set winstart to last +1
2428  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2429  }
2430  return true;
2431  }
2432  return false;
2433  }
2434  else
2435  {
2436  return StoreMpduIfNeeded (packet, hdr);
2437  }
2438 }
2439 
2440 bool
2442 {
2443  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2444  if (it != m_bAckAgreements.end ())
2445  {
2446  WifiMacTrailer fcs;
2447  packet->RemoveTrailer (fcs);
2448  BufferedPacket bufferedPacket (packet, hdr);
2449 
2450  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2451  uint16_t mappedSeqControl = QosUtilsMapSeqControlToUniqueInteger (hdr.GetSequenceControl (), endSequence);
2452 
2453  BufferedPacketI i = (*it).second.second.begin ();
2454  for (; i != (*it).second.second.end ()
2455  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceControl (), endSequence) < mappedSeqControl; i++)
2456  {
2457  }
2458  (*it).second.second.insert (i, bufferedPacket);
2459 
2460  //Update block ack cache
2461  BlockAckCachesI j = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2462  NS_ASSERT (j != m_bAckCaches.end ());
2463  (*j).second.UpdateWithMpdu (&hdr);
2464  return true;
2465  }
2466  return false;
2467 }
2468 
2469 void
2471  uint16_t startingSeq)
2472 {
2473  uint8_t tid = respHdr->GetTid ();
2474  BlockAckAgreement agreement (originator, tid);
2475  if (respHdr->IsImmediateBlockAck ())
2476  {
2477  agreement.SetImmediateBlockAck ();
2478  }
2479  else
2480  {
2481  agreement.SetDelayedBlockAck ();
2482  }
2483  agreement.SetAmsduSupport (respHdr->IsAmsduSupported ());
2484  agreement.SetBufferSize (respHdr->GetBufferSize () + 1);
2485  agreement.SetTimeout (respHdr->GetTimeout ());
2486  agreement.SetStartingSequence (startingSeq);
2487 
2488  std::list<BufferedPacket> buffer (0);
2489  AgreementKey key (originator, respHdr->GetTid ());
2490  AgreementValue value (agreement, buffer);
2491  m_bAckAgreements.insert (std::make_pair (key, value));
2492 
2493  BlockAckCache cache;
2494  cache.Init (startingSeq, respHdr->GetBufferSize () + 1);
2495  m_bAckCaches.insert (std::make_pair (key, cache));
2496 
2497  if (respHdr->GetTimeout () != 0)
2498  {
2499  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, respHdr->GetTid ()));
2500  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2501 
2502  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2503 
2504  it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
2506  m_edcaListeners[ac],
2507  originator, tid);
2508  }
2509 }
2510 
2511 void
2513 {
2514  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2515  if (it != m_bAckAgreements.end ())
2516  {
2517  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (), originator, tid);
2518  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2519  m_bAckAgreements.erase (it);
2520 
2521  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2522  NS_ASSERT (i != m_bAckCaches.end ());
2523  m_bAckCaches.erase (i);
2524  }
2525 }
2526 
2527 void
2529 {
2530  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2531  if (it != m_bAckAgreements.end ())
2532  {
2533  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2534  uint16_t mappedStart = QosUtilsMapSeqControlToUniqueInteger (seq, endSequence);
2535  BufferedPacketI last = (*it).second.second.begin ();
2536  uint16_t guard = 0;
2537  if (last != (*it).second.second.end ())
2538  {
2539  guard = (*it).second.second.begin ()->second.GetSequenceControl ();
2540  }
2541  BufferedPacketI i = (*it).second.second.begin ();
2542  for (; i != (*it).second.second.end ()
2543  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceControl (), endSequence) < mappedStart; )
2544  {
2545  if (guard == (*i).second.GetSequenceControl ())
2546  {
2547  if (!(*i).second.IsMoreFragments ())
2548  {
2549  while (last != i)
2550  {
2551  m_rxCallback ((*last).first, &(*last).second);
2552  last++;
2553  }
2554  m_rxCallback ((*last).first, &(*last).second);
2555  last++;
2556  /* go to next packet */
2557  while (i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl ())
2558  {
2559  i++;
2560  }
2561  if (i != (*it).second.second.end ())
2562  {
2563  guard = (*i).second.GetSequenceControl ();
2564  last = i;
2565  }
2566  }
2567  else
2568  {
2569  guard++;
2570  }
2571  }
2572  else
2573  {
2574  /* go to next packet */
2575  while (i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl ())
2576  {
2577  i++;
2578  }
2579  if (i != (*it).second.second.end ())
2580  {
2581  guard = (*i).second.GetSequenceControl ();
2582  last = i;
2583  }
2584  }
2585  }
2586  (*it).second.second.erase ((*it).second.second.begin (), i);
2587  }
2588 }
2589 
2590 void
2592 {
2593  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2594  if (it != m_bAckAgreements.end ())
2595  {
2596  uint16_t guard = (*it).second.first.GetStartingSequenceControl ();
2597  BufferedPacketI lastComplete = (*it).second.second.begin ();
2598  BufferedPacketI i = (*it).second.second.begin ();
2599  for (; i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl (); i++)
2600  {
2601  if (!(*i).second.IsMoreFragments ())
2602  {
2603  while (lastComplete != i)
2604  {
2605  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2606  lastComplete++;
2607  }
2608  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2609  lastComplete++;
2610  }
2611  guard = (*i).second.IsMoreFragments () ? (guard + 1) : ((guard + 16) & 0xfff0);
2612  }
2613  (*it).second.first.SetStartingSequenceControl (guard);
2614  /* All packets already forwarded to WifiMac must be removed from buffer:
2615  [begin (), lastComplete) */
2616  (*it).second.second.erase ((*it).second.second.begin (), lastComplete);
2617  }
2618 }
2619 void
2620 MacLow::SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate,
2621  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2622 {
2623  Ptr<Packet> packet = Create<Packet> ();
2624  packet->AddHeader (*blockAck);
2625 
2626  WifiMacHeader hdr;
2628  hdr.SetAddr1 (originator);
2629  hdr.SetAddr2 (GetAddress ());
2630  hdr.SetDsNotFrom ();
2631  hdr.SetDsNotTo ();
2632  hdr.SetNoRetry ();
2633  hdr.SetNoMoreFragments ();
2634 
2635  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (originator, blockAckReqTxMode);
2636 
2637  m_currentPacket = packet;
2638  m_currentHdr = hdr;
2639  if (immediate)
2640  {
2642  duration -= GetSifs ();
2643  if (blockAck->IsBasic ())
2644  {
2645  duration -= GetBlockAckDuration (originator, blockAckReqTxVector, BASIC_BLOCK_ACK);
2646  }
2647  else if (blockAck->IsCompressed ())
2648  {
2649  duration -= GetBlockAckDuration (originator, blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2650  }
2651  else if (blockAck->IsMultiTid ())
2652  {
2653  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2654  }
2655  }
2656  else
2657  {
2658  m_txParams.EnableAck ();
2659  duration += GetSifs ();
2660  duration += GetAckDuration (originator, blockAckReqTxVector);
2661  }
2663 
2664  if (!immediate)
2665  {
2666  StartDataTxTimers (blockAckReqTxVector);
2667  }
2668 
2669  NS_ASSERT (duration >= NanoSeconds (0));
2670  hdr.SetDuration (duration);
2671  //here should be present a control about immediate or delayed block ack
2672  //for now we assume immediate
2673  packet->AddHeader (hdr);
2674  WifiMacTrailer fcs;
2675  packet->AddTrailer (fcs);
2676  WifiPreamble preamble;
2677  if (blockAckReqTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
2678  {
2679  preamble = WIFI_PREAMBLE_HT_MF;
2680  }
2682  {
2683  preamble = WIFI_PREAMBLE_SHORT;
2684  }
2685  else
2686  {
2687  preamble = WIFI_PREAMBLE_LONG;
2688  }
2689  SnrTag tag;
2690  tag.Set (rxSnr);
2691  packet->AddPacketTag (tag);
2692  ForwardDown (packet, &hdr, blockAckReqTxVector, preamble);
2693  m_currentPacket = 0;
2694 }
2695 
2696 void
2697 MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector, double rxSnr)
2698 {
2699  NS_LOG_FUNCTION (this << (uint16_t) tid << originator << duration.As (Time::S) << blockAckReqTxVector << rxSnr);
2700  CtrlBAckResponseHeader blockAck;
2701  uint16_t seqNumber = 0;
2702  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2703  NS_ASSERT (i != m_bAckCaches.end ());
2704  seqNumber = (*i).second.GetWinStart ();
2705 
2706  bool immediate = true;
2707  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2708  blockAck.SetStartingSequence (seqNumber);
2709  blockAck.SetTidInfo (tid);
2710  immediate = (*it).second.first.IsImmediateBlockAck ();
2711  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2712  NS_LOG_DEBUG ("Got Implicit block Ack Req with seq " << seqNumber);
2713  (*i).second.FillBlockAckBitmap (&blockAck);
2714 
2715  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxVector.GetMode (), rxSnr);
2716 }
2717 
2718 void
2720  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2721 {
2722  NS_LOG_FUNCTION (this);
2723  CtrlBAckResponseHeader blockAck;
2724  uint8_t tid = 0;
2725  bool immediate = false;
2726  if (!reqHdr.IsMultiTid ())
2727  {
2728  tid = reqHdr.GetTidInfo ();
2729  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2730  if (it != m_bAckAgreements.end ())
2731  {
2732  blockAck.SetStartingSequence (reqHdr.GetStartingSequence ());
2733  blockAck.SetTidInfo (tid);
2734  immediate = (*it).second.first.IsImmediateBlockAck ();
2735  if (reqHdr.IsBasic ())
2736  {
2737  blockAck.SetType (BASIC_BLOCK_ACK);
2738  }
2739  else if (reqHdr.IsCompressed ())
2740  {
2741  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2742  }
2743  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2744  NS_ASSERT (i != m_bAckCaches.end ());
2745  (*i).second.FillBlockAckBitmap (&blockAck);
2746  NS_LOG_DEBUG ("Got block Ack Req with seq " << reqHdr.GetStartingSequence ());
2747 
2749  {
2750  /* All packets with smaller sequence than starting sequence control must be passed up to Wifimac
2751  * See 9.10.3 in IEEE 802.11e standard.
2752  */
2754  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2755  }
2756  else
2757  {
2758  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), reqHdr.GetStartingSequence ()))
2759  {
2760  (*it).second.first.SetStartingSequence (reqHdr.GetStartingSequence ());
2761  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2763  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2764  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2765  }
2766  }
2767  }
2768  else
2769  {
2770  NS_LOG_DEBUG ("there's not a valid block ack agreement with " << originator);
2771  }
2772  }
2773  else
2774  {
2775  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2776  }
2777 
2778  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode, rxSnr);
2779 }
2780 
2781 void
2783 {
2784  if (agreement.GetTimeout () != 0)
2785  {
2786  NS_ASSERT (agreement.m_inactivityEvent.IsRunning ());
2787  agreement.m_inactivityEvent.Cancel ();
2788  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2789  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2790  agreement.m_inactivityEvent = Simulator::Schedule (timeout,
2792  m_edcaListeners[ac],
2793  agreement.GetPeer (),
2794  agreement.GetTid ());
2795  }
2796 }
2797 
2798 void
2800 {
2801  m_edcaListeners.insert (std::make_pair (ac, listener));
2802 }
2803 
2804 void
2805 MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiTxVector txVector, WifiPreamble preamble)
2806 {
2807  NS_LOG_FUNCTION (this);
2808  AmpduTag ampdu;
2809  bool normalAck = false;
2810  bool ampduSubframe = false; //flag indicating the packet belongs to an A-MPDU and is not a VHT single MPDU
2811  if (aggregatedPacket->RemovePacketTag (ampdu))
2812  {
2813  ampduSubframe = true;
2815  MpduAggregator::DeaggregatedMpdusCI n = packets.begin ();
2816 
2817  WifiMacHeader firsthdr;
2818  (*n).first->PeekHeader (firsthdr);
2819  NS_LOG_DEBUG ("duration/id=" << firsthdr.GetDuration ());
2820  NotifyNav ((*n).first, firsthdr, preamble);
2821 
2822  if (firsthdr.GetAddr1 () == m_self)
2823  {
2824  bool vhtSingleMpdu = (*n).second.GetEof ();
2825  if (vhtSingleMpdu)
2826  {
2827  //If the MPDU is sent as a VHT single MPDU (EOF=1 in A-MPDU subframe header), then the responder sends an ACK.
2828  NS_LOG_DEBUG ("Receive VHT single MPDU");
2829  ampduSubframe = false;
2830  }
2831  else if (preamble != WIFI_PREAMBLE_NONE || !m_sendAckEvent.IsRunning ())
2832  {
2835  firsthdr.GetQosTid (),
2836  firsthdr.GetAddr2 (),
2837  firsthdr.GetDuration (),
2838  txVector,
2839  rxSnr);
2840  }
2841 
2842  if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ())
2843  {
2844  ReceiveOk ((*n).first, rxSnr, txVector, preamble, ampduSubframe);
2845  }
2846  else if (firsthdr.IsData () || firsthdr.IsQosData ())
2847  {
2848  NS_LOG_DEBUG ("Deaggregate packet from " << firsthdr.GetAddr2 () << " with sequence=" << firsthdr.GetSequenceNumber ());
2849  ReceiveOk ((*n).first, rxSnr, txVector, preamble, ampduSubframe);
2850  if (firsthdr.IsQosAck ())
2851  {
2852  NS_LOG_DEBUG ("Normal Ack");
2853  normalAck = true;
2854  }
2855  }
2856  else
2857  {
2858  NS_FATAL_ERROR ("Received A-MPDU with invalid first MPDU type");
2859  }
2860 
2861  if (ampdu.GetRemainingNbOfMpdus () == 0 && !vhtSingleMpdu)
2862  {
2863  if (normalAck)
2864  {
2865  //send block Ack
2866  if (firsthdr.IsBlockAckReq ())
2867  {
2868  NS_FATAL_ERROR ("Sending a BlockAckReq with QosPolicy equal to Normal Ack");
2869  }
2870  uint8_t tid = firsthdr.GetQosTid ();
2871  AgreementsI it = m_bAckAgreements.find (std::make_pair (firsthdr.GetAddr2 (), tid));
2872  if (it != m_bAckAgreements.end ())
2873  {
2874  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
2875  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
2876  NS_LOG_DEBUG ("rx A-MPDU/sendImmediateBlockAck from=" << firsthdr.GetAddr2 ());
2878  }
2879  else
2880  {
2881  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
2882  }
2883  }
2884  }
2885  }
2886  }
2887  else
2888  {
2889  ReceiveOk (aggregatedPacket, rxSnr, txVector, preamble, ampduSubframe);
2890  }
2891 }
2892 
2893 bool
2894 MacLow::StopMpduAggregation (Ptr<const Packet> peekedPacket, WifiMacHeader peekedHdr, Ptr<Packet> aggregatedPacket, uint16_t size) const
2895 {
2896  if (peekedPacket == 0)
2897  {
2898  NS_LOG_DEBUG ("no more packets in queue");
2899  return true;
2900  }
2901 
2902  WifiPreamble preamble;
2903 
2904  uint8_t tid = GetTid (peekedPacket, peekedHdr);
2905  AcIndex ac = QosUtilsMapTidToAc (tid);
2906  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt = m_edcaListeners.find (ac);
2907 
2909  {
2910  preamble = WIFI_PREAMBLE_VHT;
2911  }
2913  {
2914  preamble = WIFI_PREAMBLE_HT_GF;
2915  }
2917  {
2918  preamble = WIFI_PREAMBLE_HT_MF;
2919  }
2921  {
2922  preamble = WIFI_PREAMBLE_SHORT;
2923  }
2924  else
2925  {
2926  preamble = WIFI_PREAMBLE_LONG;
2927  }
2928 
2929  //An HT STA shall not transmit a PPDU that has a duration that is greater than aPPDUMaxTime (10 milliseconds)
2930  if (m_phy->CalculateTxDuration (aggregatedPacket->GetSize () + peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, m_currentTxVector, preamble, m_phy->GetFrequency ()) > MilliSeconds (10))
2931  {
2932  NS_LOG_DEBUG ("no more packets can be aggregated to satisfy PPDU <= aPPDUMaxTime");
2933  return true;
2934  }
2935 
2936  if (!listenerIt->second->GetMpduAggregator ()->CanBeAggregated (peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, aggregatedPacket, size))
2937  {
2938  NS_LOG_DEBUG ("no more packets can be aggregated because the maximum A-MPDU size has been reached");
2939  return true;
2940  }
2941 
2942  return false;
2943 }
2944 
2947 {
2948  NS_ASSERT (m_aggregateQueue->GetSize () == 0);
2949  bool isAmpdu = false;
2950  Ptr<Packet> newPacket, tempPacket;
2951  WifiMacHeader peekedHdr;
2952  newPacket = packet->Copy ();
2953  Ptr<Packet> currentAggregatedPacket;
2954  CtrlBAckRequestHeader blockAckReq;
2955 
2956  if (hdr.IsBlockAckReq ())
2957  {
2958  //Workaround to avoid BlockAckReq to be part of an A-MPDU. The standard says that
2959  //BlockAckReq is not present in A-MPDU if any QoS data frames for that TID are present.
2960  //Since an A-MPDU in non-PSMP frame exchanges aggregates MPDUs from one TID, this means
2961  //we should stop aggregation here for single-TID A-MPDUs. Once PSMP and multi-TID A-MPDUs
2962  //are supported, the condition of entering here should be changed.
2963  return newPacket;
2964  }
2965 
2966  //missing hdr.IsAck() since we have no means of knowing the Tid of the Ack yet
2967  if (hdr.IsQosData () || hdr.IsBlockAck ()|| hdr.IsBlockAckReq ())
2968  {
2969  Time tstamp;
2970  uint8_t tid = GetTid (packet, hdr);
2971  Ptr<WifiMacQueue> queue;
2972  AcIndex ac = QosUtilsMapTidToAc (tid);
2973  //since a blockack agreement always preceeds mpdu aggregation there should always exist blockAck listener
2974  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt = m_edcaListeners.find (ac);
2975  NS_ASSERT (listenerIt != m_edcaListeners.end ());
2976  queue = listenerIt->second->GetQueue ();
2977 
2978  if (!hdr.GetAddr1 ().IsBroadcast () && listenerIt->second->GetMpduAggregator () != 0)
2979  {
2980  //Have to make sure that their exist a block Ack agreement before sending an AMPDU (BlockAck Manager)
2981  if (listenerIt->second->GetBlockAckAgreementExists (hdr.GetAddr1 (), tid))
2982  {
2983  /* here is performed mpdu aggregation */
2984  /* MSDU aggregation happened in edca if the user asked for it so m_currentPacket may contains a normal packet or a A-MSDU*/
2985  currentAggregatedPacket = Create<Packet> ();
2986  peekedHdr = hdr;
2987  uint16_t startingSequenceNumber = 0;
2988  uint16_t currentSequenceNumber = 0;
2989  uint8_t qosPolicy = 0;
2990  uint16_t blockAckSize = 0;
2991  bool aggregated = false;
2992  int i = 0;
2993  Ptr<Packet> aggPacket = newPacket->Copy ();
2994 
2995  if (!hdr.IsBlockAckReq ())
2996  {
2997  if (!hdr.IsBlockAck ())
2998  {
2999  startingSequenceNumber = peekedHdr.GetSequenceNumber ();
3000  peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
3001  }
3002  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
3003  newPacket->AddHeader (peekedHdr);
3004  WifiMacTrailer fcs;
3005  newPacket->AddTrailer (fcs);
3006 
3007  aggregated = listenerIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
3008 
3009  if (aggregated)
3010  {
3011  NS_LOG_DEBUG ("Adding packet with Sequence number " << peekedHdr.GetSequenceNumber () << " to A-MPDU, packet size = " << newPacket->GetSize () << ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
3012  i++;
3013  m_sentMpdus++;
3014  m_aggregateQueue->Enqueue (aggPacket, peekedHdr);
3015  }
3016  }
3017  else if (hdr.IsBlockAckReq ())
3018  {
3019  blockAckSize = packet->GetSize () + hdr.GetSize () + WIFI_MAC_FCS_LENGTH;
3020  qosPolicy = 3; //if the last subrame is block ack req then set ack policy of all frames to blockack
3021  packet->PeekHeader (blockAckReq);
3022  startingSequenceNumber = blockAckReq.GetStartingSequence ();
3023  }
3025  aggregated = false;
3026  bool retry = false;
3027  //looks for other packets to the same destination with the same Tid need to extend that to include MSDUs
3028  Ptr<const Packet> peekedPacket = listenerIt->second->PeekNextPacketInBaQueue (peekedHdr, peekedHdr.GetAddr1 (), tid, &tstamp);
3029  if (peekedPacket == 0)
3030  {
3031  peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
3033  hdr.GetAddr1 (), &tstamp);
3034  currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr);
3035 
3036  /* here is performed MSDU aggregation (two-level aggregation) */
3037  if (peekedPacket != 0 && listenerIt->second->GetMsduAggregator () != 0)
3038  {
3039  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
3040  if (tempPacket != 0) //MSDU aggregation
3041  {
3042  peekedPacket = tempPacket->Copy ();
3043  }
3044  }
3045  }
3046  else
3047  {
3048  retry = true;
3049  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
3050  }
3051 
3052  while (IsInWindow (currentSequenceNumber, startingSequenceNumber, 64) && !StopMpduAggregation (peekedPacket, peekedHdr, currentAggregatedPacket, blockAckSize))
3053  {
3054  //for now always send AMPDU with normal ACK
3055  if (retry == false)
3056  {
3057  currentSequenceNumber = listenerIt->second->GetNextSequenceNumberfor (&peekedHdr);
3058  peekedHdr.SetSequenceNumber (currentSequenceNumber);
3059  peekedHdr.SetFragmentNumber (0);
3060  peekedHdr.SetNoMoreFragments ();
3061  peekedHdr.SetNoRetry ();
3062  }
3063  if (qosPolicy == 0)
3064  {
3065  peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
3066  }
3067  else
3068  {
3069  peekedHdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK);
3070  }
3071 
3072  newPacket = peekedPacket->Copy ();
3073  Ptr<Packet> aggPacket = newPacket->Copy ();
3074 
3075  newPacket->AddHeader (peekedHdr);
3076  WifiMacTrailer fcs;
3077  newPacket->AddTrailer (fcs);
3078  aggregated = listenerIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
3079  if (aggregated)
3080  {
3081  m_aggregateQueue->Enqueue (aggPacket, peekedHdr);
3082  if (i == 1 && hdr.IsQosData ())
3083  {
3084  if (!m_txParams.MustSendRts ())
3085  {
3086  listenerIt->second->CompleteMpduTx (packet, hdr, tstamp);
3087  }
3088  else
3089  {
3090  InsertInTxQueue (packet, hdr, tstamp);
3091  }
3092  }
3093  NS_LOG_DEBUG ("Adding packet with Sequence number " << peekedHdr.GetSequenceNumber () << " to A-MPDU, packet size = " << newPacket->GetSize () << ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
3094  i++;
3095  isAmpdu = true;
3096  m_sentMpdus++;
3097  if (!m_txParams.MustSendRts ())
3098  {
3099  listenerIt->second->CompleteMpduTx (peekedPacket, peekedHdr, tstamp);
3100  }
3101  else
3102  {
3103  InsertInTxQueue (peekedPacket, peekedHdr, tstamp);
3104  }
3105  if (retry)
3106  {
3107  listenerIt->second->RemoveFromBaQueue (tid, hdr.GetAddr1 (), peekedHdr.GetSequenceNumber ());
3108  }
3109  else
3110  {
3111  queue->Remove (peekedPacket);
3112  }
3113  newPacket = 0;
3114  }
3115  else
3116  {
3117  break;
3118  }
3119  if (retry == true)
3120  {
3121  peekedPacket = listenerIt->second->PeekNextPacketInBaQueue (peekedHdr, hdr.GetAddr1 (), tid, &tstamp);
3122  if (peekedPacket == 0)
3123  {
3124  //I reached the first packet that I added to this A-MPDU
3125  retry = false;
3126  peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
3127  WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp);
3128  if (peekedPacket != 0)
3129  {
3130  //find what will the sequence number be so that we don't send more than 64 packets apart
3131  currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr);
3132 
3133  if (listenerIt->second->GetMsduAggregator () != 0)
3134  {
3135  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
3136  if (tempPacket != 0) //MSDU aggregation
3137  {
3138  peekedPacket = tempPacket->Copy ();
3139  }
3140  }
3141  }
3142  }
3143  else
3144  {
3145  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
3146  }
3147  }
3148  else
3149  {
3150  peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
3151  WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp);
3152  if (peekedPacket != 0)
3153  {
3154  //find what will the sequence number be so that we don't send more than 64 packets apart
3155  currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr);
3156 
3157  if (listenerIt->second->GetMsduAggregator () != 0 && IsInWindow (currentSequenceNumber, startingSequenceNumber, 64))
3158  {
3159  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
3160  if (tempPacket != 0) //MSDU aggregation
3161  {
3162  peekedPacket = tempPacket->Copy ();
3163  }
3164  }
3165  }
3166  }
3167  }
3168 
3169  if (isAmpdu)
3170  {
3171  if (hdr.IsBlockAckReq ())
3172  {
3173  newPacket = packet->Copy ();
3174  peekedHdr = hdr;
3175  Ptr<Packet> aggPacket = newPacket->Copy ();
3176  m_aggregateQueue->Enqueue (aggPacket, peekedHdr);
3177  newPacket->AddHeader (peekedHdr);
3178  WifiMacTrailer fcs;
3179  newPacket->AddTrailer (fcs);
3180  listenerIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
3181  currentAggregatedPacket->AddHeader (blockAckReq);
3182  }
3183 
3184  if (qosPolicy == 0)
3185  {
3186  listenerIt->second->CompleteTransfer (hdr.GetAddr1 (), tid);
3187  }
3188 
3189  //Add packet tag
3190  AmpduTag ampdutag;
3191  ampdutag.SetAmpdu (true);
3192  ampdutag.SetRemainingNbOfMpdus (i - 1);
3193  newPacket = currentAggregatedPacket;
3194  newPacket->AddPacketTag (ampdutag);
3195 
3196  NS_LOG_DEBUG ("tx unicast A-MPDU");
3197  listenerIt->second->SetAmpdu (hdr.GetAddr1 (), true);
3198  }
3199  else
3200  {
3201  uint32_t queueSize = m_aggregateQueue->GetSize ();
3202  NS_ASSERT (queueSize <= 2); //since it is not an A-MPDU then only 2 packets should have been added to the queue no more
3203  if (queueSize >= 1)
3204  {
3205  //remove any packets that we added to the aggregate queue
3207  }
3208  }
3209  }
3210  //VHT single MPDU operation
3212  if (!isAmpdu && dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_VHT && hdr.IsQosData ())
3213  {
3214  peekedHdr = hdr;
3216 
3217  currentAggregatedPacket = Create<Packet> ();
3218  listenerIt->second->GetMpduAggregator ()->AggregateVhtSingleMpdu (packet, currentAggregatedPacket);
3219  m_aggregateQueue->Enqueue (packet, peekedHdr);
3220  m_sentMpdus = 1;
3221 
3222  if (listenerIt->second->GetBlockAckAgreementExists (hdr.GetAddr1 (), tid))
3223  {
3224  listenerIt->second->CompleteTransfer (peekedHdr.GetAddr1 (), tid);
3225  }
3226 
3227  //Add packet tag
3228  AmpduTag ampdutag;
3229  ampdutag.SetAmpdu (true);
3230  newPacket = currentAggregatedPacket;
3231  newPacket->AddHeader (peekedHdr);
3232  WifiMacTrailer fcs;
3233  newPacket->AddTrailer (fcs);
3234  newPacket->AddPacketTag (ampdutag);
3235 
3236  NS_LOG_DEBUG ("tx unicast VHT single MPDU with sequence number " << hdr.GetSequenceNumber ());
3237  listenerIt->second->SetAmpdu (hdr.GetAddr1 (), true);
3238  }
3239  }
3240  }
3241  return newPacket;
3242 }
3243 
3244 void
3246 {
3247  if (m_aggregateQueue->GetSize () > 0)
3248  {
3249  NS_LOG_DEBUG ("Flush aggregate queue");
3250  m_aggregateQueue->Flush ();
3251  }
3252  m_txPackets.clear ();
3253 }
3254 
3255 void
3257 {
3258  Item item;
3259 
3260  item.packet = packet;
3261  item.hdr = hdr;
3262  item.timestamp = tStamp;
3263 
3264  m_txPackets.push_back (item);
3265 }
3266 
3268 MacLow::PerformMsduAggregation (Ptr<const Packet> packet, WifiMacHeader *hdr, Time *tstamp, Ptr<Packet> currentAmpduPacket, uint16_t blockAckSize)
3269 {
3270  bool msduAggregation = false;
3271  bool isAmsdu = false;
3272  Ptr<Packet> currentAmsduPacket = Create<Packet> ();
3273  Ptr<Packet> tempPacket = Create<Packet> ();
3274 
3275  Ptr<WifiMacQueue> queue;
3276  AcIndex ac = QosUtilsMapTidToAc (GetTid (packet, *hdr));
3277  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt = m_edcaListeners.find (ac);
3278  NS_ASSERT (listenerIt != m_edcaListeners.end ());
3279  queue = listenerIt->second->GetQueue ();
3280 
3281  Ptr<const Packet> peekedPacket = queue->DequeueByTidAndAddress (hdr, hdr->GetQosTid (),
3282  WifiMacHeader::ADDR1, hdr->GetAddr1 ());
3283 
3284  listenerIt->second->GetMsduAggregator ()->Aggregate (packet, currentAmsduPacket,
3285  listenerIt->second->GetSrcAddressForAggregation (*hdr),
3286  listenerIt->second->GetDestAddressForAggregation (*hdr));
3287 
3288  peekedPacket = queue->PeekByTidAndAddress (hdr, hdr->GetQosTid (),
3289  WifiMacHeader::ADDR1, hdr->GetAddr1 (), tstamp);
3290  while (peekedPacket != 0)
3291  {
3292  tempPacket = currentAmsduPacket;
3293 
3294  msduAggregation = listenerIt->second->GetMsduAggregator ()->Aggregate (peekedPacket, tempPacket,
3295  listenerIt->second->GetSrcAddressForAggregation (*hdr),
3296  listenerIt->second->GetDestAddressForAggregation (*hdr));
3297 
3298  if (msduAggregation && !StopMpduAggregation (tempPacket, *hdr, currentAmpduPacket, blockAckSize))
3299  {
3300  isAmsdu = true;
3301  currentAmsduPacket = tempPacket;
3302  queue->Remove (peekedPacket);
3303  }
3304  else
3305  {
3306  break;
3307  }
3308  peekedPacket = queue->PeekByTidAndAddress (hdr, hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 (), tstamp);
3309  }
3310 
3311  if (isAmsdu)
3312  {
3313  NS_LOG_DEBUG ("A-MSDU with size = " << currentAmsduPacket->GetSize ());
3314  hdr->SetQosAmsdu ();
3315  hdr->SetAddr3 (GetBssid ());
3316  return currentAmsduPacket;
3317  }
3318  else
3319  {
3320  queue->PushFront (packet, *hdr);
3321  return 0;
3322  }
3323 }
3324 
3325 } //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:674
uint32_t GetAckSize(void) const
Return the total ACK size (including FCS trailer).
Definition: mac-low.cc:1228
virtual ~MacLowDcfListener()
Definition: mac-low.cc:65
void SetPifs(Time pifs)
Set PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:602
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:527
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:2782
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:1289
Callback template class.
Definition: callback.h:1176
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
uint8_t GetRemainingNbOfMpdus(void) const
Definition: ampdu-tag.cc:110
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:1273
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:2719
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:620
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:1556
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:686
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:1567
void FastAckFailedTimeout(void)
Event handler when fast ACK timeout occurs (busy).
Definition: mac-low.cc:2337
Mac48Address GetBssid(void) const
Return the Basic Service Set Identification.
Definition: mac-low.cc:680
void SetSifs(Time sifs)
Set Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:590
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:384
WifiTxVector GetCtsToSelfTxVector(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return a TXVECTOR for the CTS-to-self frame.
Definition: mac-low.cc:1359
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:2799
void SetupPhyMacLowListener(Ptr< WifiPhy > phy)
Set up WifiPhy listener for this MacLow.
Definition: mac-low.cc:400
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:792
static DeaggregatedMpdus Deaggregate(Ptr< Packet > aggregatedPacket)
Deaggregates an A-MPDU by removing the A-MPDU subframe header and padding.
bool IsBroadcast(void) const
void NotifySleepNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:871
uint8_t GetTid(Ptr< const Packet > packet, const WifiMacHeader hdr) const
Definition: mac-low.cc:1205
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:162
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
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:692
void DeaggregateAmpduAndReceive(Ptr< Packet > aggregatedPacket, double rxSnr, WifiTxVector txVector, WifiPreamble preamble)
Definition: mac-low.cc:2805
Time GetCompressedBlockAckTimeout() const
Return Compressed Block ACK timeout of this MacLow.
Definition: mac-low.cc:644
Callback< R > MakeNullCallback(void)
Definition: callback.h:1635
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:2946
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:650
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:1319
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:3268
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:2323
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:572
void NormalAckTimeout(void)
Event handler when normal ACK timeout occurs.
Definition: mac-low.cc:1754
void SetBasicBlockAckTimeout(Time blockAckTimeout)
Set Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:560
bool IsAmsduSupported(void) const
Return whether A-MSDU capability is supported.
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:3256
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:407
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:2512
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:2085
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:59
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:2347
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1221
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:2470
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:1505
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:1236
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
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:919
receive notifications about phy events.
Definition: wifi-phy.h:70
void CtsTimeout(void)
Event handler when CTS timeout occurs.
Definition: mac-low.cc:1734
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:2329
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:2697
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:1386
void SetAckTimeout(Time ackTimeout)
Set ACK timeout of this MacLow.
Definition: mac-low.cc:554
static TypeId GetTypeId(void)
Register this type.
Definition: mac-low.cc:389
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:2223
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:662
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:1547
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:1489
bool NeedRts(void)
Check if the current packet should be sent with a RTS protection.
Definition: mac-low.cc:826
Mac48Address GetAddress(void) const
Return the MAC address of this MacLow.
Definition: mac-low.cc:626
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:38
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:1404
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:698
virtual uint32_t GetSerializedSize(void) const
void NotifySwitchingStartNow(Time duration)
Definition: mac-low.cc:855
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:446
virtual void StartTransmission(Ptr< const Packet > packet, const WifiMacHeader *hdr, MacLowTransmissionParameters parameters, MacLowTransmissionListener *listener)
Definition: mac-low.cc:723
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:1789
void NotifyCtsTimeoutStartNow(Time duration)
Notify DcfManager (via DcfListener) that CTS timer should be started for the given duration...
Definition: mac-low.cc:1603
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
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:1802
void SetBssid(Mac48Address ad)
Set the Basic Service Set Identification.
Definition: mac-low.cc:614
virtual void UnregisterListener(WifiPhyListener *listener)=0
uint32_t GetRtsSize(void) const
Return the total RTS size (including FCS trailer).
Definition: mac-low.cc:1258
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:1469
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:1907
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:1612
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:834
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:2620
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:2390
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:1771
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:2528
void SendCtsAfterRts(Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
Send CTS after receiving RTS.
Definition: mac-low.cc:2180
void SetPhy(Ptr< WifiPhy > phy)
Set up WifiPhy associated with this MacLow.
Definition: mac-low.cc:518
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:1727
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:668
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 ReceiveError(Ptr< Packet > packet, double rxSnr)
Definition: mac-low.cc:841
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:1365
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:1372
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:1381
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:2396
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:608
virtual void DoDispose(void)
Destructor implementation.
Definition: mac-low.cc:418
void NotifyAckTimeoutResetNow()
Notify DcfManager (via DcfListener) that ACK timer should be resetted.
Definition: mac-low.cc:1594
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:1410
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:1392
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:2072
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:1585
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:596
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:656
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:2894
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:1382
bool GetCtsToSelfSupported() const
Return whether CTS-to-self capability is supported.
Definition: mac-low.cc:578
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:886
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:584
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:632
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:1993
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:1335
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:548
second
Definition: nstime.h:114
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:1621
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
void SetRemainingNbOfMpdus(uint8_t nbofmpdus)
Definition: ampdu-tag.cc:65
WifiTxVector GetBlockAckTxVector(Mac48Address address, WifiMode dataMode)
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:704
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:3245
virtual ~PhyMacLowListener()
Definition: mac-low.cc:321
void ResetPhy(void)
Remove WifiPhy associated with this MacLow.
Definition: mac-low.cc:533
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:1398
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
Time GetBasicBlockAckTimeout() const
Return Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:638
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:827
Time GetRemainingAmpduDuration(void) const
Definition: ampdu-tag.cc:116
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:1380
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:2441
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:719
bool MustWaitNormalAck(void) const
Definition: mac-low.cc:213
virtual bool GetGreenfield(void) const =0
virtual ~MacLow()
Definition: mac-low.cc:382
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:566
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:542
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:1343
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:1821
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:2591
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
void SetRemainingAmpduDuration(Time duration)
Definition: ampdu-tag.cc:72