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