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