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