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  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  * Author: 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 
31 #include "mac-low.h"
32 #include "wifi-phy.h"
33 #include "wifi-mac-trailer.h"
34 #include "qos-utils.h"
35 #include "edca-txop-n.h"
36 #include "snr-tag.h"
37 #include "yans-wifi-phy.h"
38 #include "ampdu-tag.h"
39 #include "wifi-mac-queue.h"
40 #include "mpdu-aggregator.h"
41 
42 #undef NS_LOG_APPEND_CONTEXT
43 #define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_self << "] "
44 
45 
46 namespace ns3 {
47 
48 NS_LOG_COMPONENT_DEFINE ("MacLow");
49 
51 {
52 }
54 {
55 }
56 void
58 {
59 }
60 void
62 {
63 }
64 
66 {
67 }
69 {
70 }
71 
73 {
74 }
76 {
77 }
78 
80 {
81 }
83 {
84 }
85 void
87 {
88 }
89 uint16_t
91 {
92  return 0;
93 }
94 uint16_t
96 {
97  return 0;
98 }
101 {
102  return 0;
103 }
104 void
106 {
107 }
108 uint32_t
110 {
111  return 0;
112 }
113 uint32_t
115 {
116  return 0;
117 }
120 {
121  return 0;
122 }
125 {
126  return 0;
127 }
130 {
131  return 0;
132 }
133 
135  : m_nextSize (0),
136  m_waitAck (ACK_NONE),
137  m_sendRts (false),
138  m_overrideDurationId (Seconds (0))
139 {
140 }
141 void
143 {
144  m_nextSize = size;
145 }
146 void
148 {
149  m_nextSize = 0;
150 }
151 void
153 {
154  m_overrideDurationId = durationId;
155 }
156 void
158 {
160 }
161 void
163 {
165 }
166 void
168 {
170 }
171 void
173 {
175 }
176 void
178 {
180 }
181 void
183 {
185 }
186 void
188 {
190 }
191 void
193 {
195 }
196 void
198 {
199  m_sendRts = true;
200 }
201 void
203 {
204  m_sendRts = false;
205 }
206 bool
208 {
209  return (m_waitAck != ACK_NONE);
210 }
211 bool
213 {
214  return (m_waitAck == ACK_NORMAL);
215 }
216 bool
218 {
219  return (m_waitAck == ACK_FAST);
220 }
221 bool
223 {
224  return (m_waitAck == ACK_SUPER_FAST);
225 }
226 bool
228 {
229  return (m_waitAck == BLOCK_ACK_BASIC) ? true : false;
230 }
231 bool
233 {
234  return (m_waitAck == BLOCK_ACK_COMPRESSED) ? true : false;
235 }
236 bool
238 {
239  return (m_waitAck == BLOCK_ACK_MULTI_TID) ? true : false;
240 }
241 bool
243 {
244  return m_sendRts;
245 }
246 bool
248 {
249  return (m_overrideDurationId != Seconds (0));
250 }
251 Time
253 {
255  return m_overrideDurationId;
256 }
257 bool
259 {
260  return (m_nextSize != 0);
261 }
262 uint32_t
264 {
266  return m_nextSize;
267 }
268 
269 std::ostream &operator << (std::ostream &os, const MacLowTransmissionParameters &params)
270 {
271  os << "["
272  << "send rts=" << params.m_sendRts << ", "
273  << "next size=" << params.m_nextSize << ", "
274  << "dur=" << params.m_overrideDurationId << ", "
275  << "ack=";
276  switch (params.m_waitAck)
277  {
279  os << "none";
280  break;
282  os << "normal";
283  break;
285  os << "fast";
286  break;
288  os << "super-fast";
289  break;
291  os << "basic-block-ack";
292  break;
294  os << "compressed-block-ack";
295  break;
297  os << "multi-tid-block-ack";
298  break;
299  }
300  os << "]";
301  return os;
302 }
303 
304 
309 {
310 public:
317  : m_macLow (macLow)
318  {
319  }
321  {
322  }
323  virtual void NotifyRxStart (Time duration)
324  {
325  }
326  virtual void NotifyRxEndOk (void)
327  {
328  }
329  virtual void NotifyRxEndError (void)
330  {
331  }
332  virtual void NotifyTxStart (Time duration, double txPowerDbm)
333  {
334  }
335  virtual void NotifyMaybeCcaBusyStart (Time duration)
336  {
337  }
338  virtual void NotifySwitchingStart (Time duration)
339  {
340  m_macLow->NotifySwitchingStartNow (duration);
341  }
342  virtual void NotifySleep (void)
343  {
345  }
346  virtual void NotifyWakeup (void)
347  {
348  }
349 private:
351 };
352 
353 
355  : m_normalAckTimeoutEvent (),
356  m_fastAckTimeoutEvent (),
357  m_superFastAckTimeoutEvent (),
358  m_fastAckFailedTimeoutEvent (),
359  m_blockAckTimeoutEvent (),
360  m_ctsTimeoutEvent (),
361  m_sendCtsEvent (),
362  m_sendAckEvent (),
363  m_sendDataEvent (),
364  m_waitSifsEvent (),
365  m_endTxNoAckEvent (),
366  m_mpduAggregator (0),
367  m_currentPacket (0),
368  m_listener (0),
369  m_phyMacLowListener (0),
370  m_ctsToSelfSupported (false),
371  m_receivedAtLeastOneMpdu (false)
372 {
373  NS_LOG_FUNCTION (this);
375  m_lastNavStart = Seconds (0);
376  m_promisc = false;
377  m_ampdu = false;
378  m_sentMpdus = 0;
379  m_aggregateQueue = CreateObject<WifiMacQueue> ();
380 }
381 
383 {
384  NS_LOG_FUNCTION (this);
385 }
386 
387 void
389 {
392 }
393 
394 void
396 {
397  if (m_phyMacLowListener != 0 )
398  {
400  delete m_phyMacLowListener;
402  }
403 }
404 
405 void
407 {
408  NS_LOG_FUNCTION (this);
421  m_phy = 0;
422  m_stationManager = 0;
423  if (m_phyMacLowListener != 0)
424  {
425  delete m_phyMacLowListener;
427  }
428  m_mpduAggregator = 0;
429  m_sentMpdus = 0;
430  m_aggregateQueue = 0;
431  m_ampdu = false;
432 }
433 
434 void
436 {
437  NS_LOG_FUNCTION (this);
438  bool oneRunning = false;
440  {
442  oneRunning = true;
443  }
445  {
447  oneRunning = true;
448  }
450  {
452  oneRunning = true;
453  }
455  {
457  oneRunning = true;
458  }
460  {
462  oneRunning = true;
463  }
465  {
467  oneRunning = true;
468  }
469  if (m_sendCtsEvent.IsRunning ())
470  {
472  oneRunning = true;
473  }
474  if (m_sendAckEvent.IsRunning ())
475  {
477  oneRunning = true;
478  }
479  if (m_sendDataEvent.IsRunning ())
480  {
482  oneRunning = true;
483  }
484  if (m_waitSifsEvent.IsRunning ())
485  {
487  oneRunning = true;
488  }
489  if (m_waitRifsEvent.IsRunning ())
490  {
492  oneRunning = true;
493  }
495  {
497  oneRunning = true;
498  }
499  if (oneRunning && m_listener != 0)
500  {
501  m_listener->Cancel ();
502  m_listener = 0;
503  }
504 }
505 
506 void
508 {
509  m_phy = phy;
513 }
515 MacLow::GetPhy (void) const
516 {
517  return m_phy;
518 }
519 void
521 {
525  m_phy = 0;
526 }
527 void
529 {
530  m_stationManager = manager;
531 }
532 
533 void
535 {
536  m_self = ad;
537 }
538 void
540 {
541  m_ackTimeout = ackTimeout;
542 }
543 void
545 {
546  m_basicBlockAckTimeout = blockAckTimeout;
547 }
548 void
550 {
551  m_compressedBlockAckTimeout = blockAckTimeout;
552 }
553 void
555 {
556  m_ctsToSelfSupported = enable;
557 }
558 bool
560 {
561  return m_ctsToSelfSupported;
562 }
563 void
565 {
566  m_ctsTimeout = ctsTimeout;
567 }
568 void
570 {
571  m_sifs = sifs;
572 }
573 void
575 {
576  m_slotTime = slotTime;
577 }
578 void
580 {
581  m_pifs = pifs;
582 }
583 void
585 {
586  m_rifs = rifs;
587 }
588 void
590 {
591  m_bssid = bssid;
592 }
593 void
595 {
596  m_promisc = true;
597 }
599 MacLow::GetAddress (void) const
600 {
601  return m_self;
602 }
603 Time
605 {
606  return m_ackTimeout;
607 }
608 Time
610 {
611  return m_basicBlockAckTimeout;
612 }
613 Time
615 {
617 }
618 Time
620 {
621  return m_ctsTimeout;
622 }
623 Time
624 MacLow::GetSifs (void) const
625 {
626  return m_sifs;
627 }
628 Time
629 MacLow::GetRifs (void) const
630 {
631  return m_rifs;
632 }
633 Time
635 {
636  return m_slotTime;
637 }
638 Time
639 MacLow::GetPifs (void) const
640 {
641  return m_pifs;
642 }
644 MacLow::GetBssid (void) const
645 {
646  return m_bssid;
647 }
648 bool
649 MacLow::IsPromisc (void) const
650 {
651  return m_promisc;
652 }
653 
654 void
656 {
657  m_rxCallback = callback;
658 }
659 void
661 {
662  m_dcfListeners.push_back (listener);
663 }
664 
665 bool
667 {
668  uint32_t size, actualSize;
669  WifiMacTrailer fcs;
670  size = packet->GetSize () + hdr.GetSize () + fcs.GetSerializedSize ();
671  Ptr<Packet> p = AggregateToAmpdu (packet, hdr);
672  actualSize = p->GetSize();
673  if (actualSize > size)
674  {
675  m_currentPacket = p;
676  return true;
677  }
678  else
679  return false;
680 }
681 
682 void
684  const WifiMacHeader* hdr,
686  MacLowTransmissionListener *listener)
687 {
688  NS_LOG_FUNCTION (this << packet << hdr << params << listener);
689  /* m_currentPacket is not NULL because someone started
690  * a transmission and was interrupted before one of:
691  * - ctsTimeout
692  * - sendDataAfterCTS
693  * expired. This means that one of these timers is still
694  * running. They are all cancelled below anyway by the
695  * call to CancelAllEvents (because of at least one
696  * of these two timer) which will trigger a call to the
697  * previous listener's cancel method.
698  *
699  * This typically happens because the high-priority
700  * QapScheduler has taken access to the channel from
701  * one of the Edca of the QAP.
702  */
703  m_currentHdr = *hdr;
704  CancelAllEvents ();
705  m_listener = listener;
706  m_txParams = params;
707 
708  //NS_ASSERT (m_phy->IsStateIdle ());
709 
710  if(m_aggregateQueue->GetSize () == 0)
711  {
712  m_currentPacket = packet->Copy ();
714  }
715  else
716  {
717  /*m_aggregateQueue > 0 occurs when a RTS/CTS exchange failed before an A-MPDU transmission.
718  *In that case, we transmit the same A-MPDU as previously.
719  */
720  m_sentMpdus = m_aggregateQueue->GetSize ();
721  m_ampdu = true;
722  }
723 
724  NS_LOG_DEBUG ("startTx size=" << GetSize (m_currentPacket, &m_currentHdr) <<
725  ", to=" << m_currentHdr.GetAddr1 () << ", listener=" << m_listener);
726 
727  if (m_ampdu)
729 
730  if (m_txParams.MustSendRts ())
731  {
732  SendRtsForPacket ();
733  }
734  else
735  {
737  {
738  SendCtsToSelf();
739  }
740  else
741  {
742  SendDataPacket ();
743  }
744  }
745 
746  /* When this method completes, we have taken ownership of the medium. */
747  NS_ASSERT (m_phy->IsStateTx ());
748 }
749 bool
751 {
753  return m_stationManager->NeedCtsToSelf (dataTxVector);
754 }
755 void
757 {
758  NS_LOG_FUNCTION (this << packet << rxSnr);
759  NS_LOG_DEBUG ("rx failed ");
760  AmpduTag ampdu;
761  Ptr<Packet> pkt = packet->Copy();
762  bool isInAmpdu = pkt->RemovePacketTag(ampdu);
763 
764  if(isInAmpdu && m_receivedAtLeastOneMpdu && (ampdu.GetNoOfMpdus() == 1))
765  {
767  MpduAggregator::DeaggregatedMpdusCI n = packets.begin ();
768  WifiMacHeader hdr;
769  (*n).first->PeekHeader(hdr);
770  if(hdr.IsQosData())
771  {
772  NS_LOG_DEBUG ("last a-mpdu subframe detected/sendImmediateBlockAck from=" << hdr.GetAddr2 ());
775  hdr.GetQosTid(),
776  hdr.GetAddr2 (),
777  hdr.GetDuration (),
779  }
780  else if (hdr.IsBlockAckReq())
781  {
782  NS_LOG_DEBUG("last a-mpdu subframe is BAR");
783  }
784  m_receivedAtLeastOneMpdu = false;
785  }
786  else if (m_txParams.MustWaitFastAck ())
787  {
791  }
792  return;
793 }
794 
795 void
797 {
798  NS_LOG_DEBUG ("switching channel. Cancelling MAC pending events");
800  CancelAllEvents ();
802  {
804  }
807  m_currentPacket = 0;
808  m_listener = 0;
809 }
810 
811 void
813 {
814  NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
815  CancelAllEvents ();
817  {
819  }
822  m_currentPacket = 0;
823  m_listener = 0;
824 }
825 
826 void
827 MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, WifiPreamble preamble, bool ampduSubframe)
828 {
829  NS_LOG_FUNCTION (this << packet << rxSnr << txVector.GetMode () << preamble);
830  /* A packet is received from the PHY.
831  * When we have handled this packet,
832  * we handle any packet present in the
833  * packet queue.
834  */
835  WifiMacHeader hdr;
836  packet->RemoveHeader (hdr);
837 
838  bool isPrevNavZero = IsNavZero ();
839  NS_LOG_DEBUG ("duration/id=" << hdr.GetDuration ());
840  NotifyNav (packet, hdr, preamble);
841  if (hdr.IsRts ())
842  {
843  /* see section 9.2.5.7 802.11-1999
844  * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS
845  * period if the NAV at the STA receiving the RTS frame indicates that the medium is
846  * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle,
847  * that STA shall not respond to the RTS frame.
848  */
849  if (ampduSubframe)
850  {
851  NS_FATAL_ERROR ("Received RTS as part of an A-MPDU");
852  }
853  else
854  {
855  if (isPrevNavZero
856  && hdr.GetAddr1 () == m_self)
857  {
858  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
860  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
861  rxSnr, txVector.GetMode ());
864  hdr.GetAddr2 (),
865  hdr.GetDuration (),
866  txVector,
867  rxSnr);
868  }
869  else
870  {
871  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
872  }
873  }
874  }
875  else if (hdr.IsCts ()
876  && hdr.GetAddr1 () == m_self
878  && m_currentPacket != 0)
879  {
880  if (ampduSubframe)
881  {
882  NS_FATAL_ERROR ("Received CTS as part of an A-MPDU");
883  }
884  NS_LOG_DEBUG ("receive cts from=" << m_currentHdr.GetAddr1 ());
885  SnrTag tag;
886  packet->RemovePacketTag (tag);
888  rxSnr, txVector.GetMode ());
890  rxSnr, txVector.GetMode (), tag.Get ());
891 
894  m_listener->GotCts (rxSnr, txVector.GetMode ());
898  hdr.GetAddr1 (),
899  hdr.GetDuration ());
900  }
901  else if (hdr.IsAck ()
902  && hdr.GetAddr1 () == m_self
906  && m_txParams.MustWaitAck ())
907  {
908  NS_LOG_DEBUG ("receive ack from=" << m_currentHdr.GetAddr1 ());
909  SnrTag tag;
910  packet->RemovePacketTag (tag);
912  rxSnr, txVector.GetMode ());
914  rxSnr, txVector.GetMode (), tag.Get ());
915 
917  bool gotAck = false;
920  {
923  gotAck = true;
924  }
927  {
930  gotAck = true;
931  }
932  if (gotAck)
933  {
934  m_listener->GotAck (rxSnr, txVector.GetMode ());
935  }
936  if (m_txParams.HasNextPacket ())
937  {
940  }
941  }
942  else if (hdr.IsBlockAck () && hdr.GetAddr1 () == m_self
945  {
946  NS_LOG_DEBUG ("got block ack from " << hdr.GetAddr2 ());
947  CtrlBAckResponseHeader blockAck;
948  packet->RemoveHeader (blockAck);
951  m_listener->GotBlockAck (&blockAck, hdr.GetAddr2 (), txVector.GetMode ());
952  m_sentMpdus = 0;
953  m_ampdu = false;
955  }
956  else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
957  {
958  CtrlBAckRequestHeader blockAckReq;
959  packet->RemoveHeader (blockAckReq);
960  if (!blockAckReq.IsMultiTid ())
961  {
962  uint8_t tid = blockAckReq.GetTidInfo ();
963  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), tid));
964  if (it != m_bAckAgreements.end ())
965  {
966  //Update block ack cache
967  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), tid));
968  NS_ASSERT (i != m_bAckCaches.end ());
969  (*i).second.UpdateWithBlockAckReq (blockAckReq.GetStartingSequence ());
970 
972  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
973  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
974  if ((*it).second.first.IsImmediateBlockAck ())
975  {
976  NS_LOG_DEBUG ("rx blockAckRequest/sendImmediateBlockAck from=" << hdr.GetAddr2 ());
979  blockAckReq,
980  hdr.GetAddr2 (),
981  hdr.GetDuration (),
982  txVector.GetMode ());
983  }
984  else
985  {
986  NS_FATAL_ERROR ("Delayed block ack not supported.");
987  }
988  m_receivedAtLeastOneMpdu = false;
989  }
990  else
991  {
992  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
993  }
994  }
995  else
996  {
997  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
998  }
999  }
1000  else if (hdr.IsCtl ())
1001  {
1002  NS_LOG_DEBUG ("rx drop " << hdr.GetTypeString ());
1003  m_receivedAtLeastOneMpdu = false;
1004  }
1005  else if (hdr.GetAddr1 () == m_self)
1006  {
1007  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
1008  rxSnr, txVector.GetMode ());
1009  if (hdr.IsQosData () && ReceiveMpdu (packet, hdr))
1010  {
1011  /* From section 9.10.4 in IEEE 802.11:
1012  Upon the receipt of a QoS data frame from the originator for which
1013  the Block Ack agreement exists, the recipient shall buffer the MSDU
1014  regardless of the value of the Ack Policy subfield within the
1015  QoS Control field of the QoS data frame. */;
1016  if (hdr.IsQosAck () && !ampduSubframe)
1017  {
1018  NS_LOG_DEBUG ("rx QoS unicast/sendAck from=" << hdr.GetAddr2 ());
1019  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1020 
1021  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequence (),
1022  hdr.GetAddr2 (), hdr.GetQosTid ());
1023  RxCompleteBufferedPacketsUntilFirstLost (hdr.GetAddr2 (), hdr.GetQosTid ());
1026  &MacLow::SendAckAfterData, this,
1027  hdr.GetAddr2 (),
1028  hdr.GetDuration (),
1029  txVector.GetMode (),
1030  rxSnr);
1031  m_receivedAtLeastOneMpdu = false;
1032  }
1033  else if (hdr.IsQosBlockAck ())
1034  {
1035  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1036  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
1037  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
1038  }
1039  return;
1040  }
1041  else if (hdr.IsQosData () && hdr.IsQosBlockAck ())
1042  {
1043  /* This happens if a packet with ack policy Block Ack is received and a block ack
1044  agreement for that packet doesn't exist.
1045 
1046  From section 11.5.3 in IEEE 802.11e:
1047  When a recipient does not have an active Block ack for a TID, but receives
1048  data MPDUs with the Ack Policy subfield set to Block Ack, it shall discard
1049  them and shall send a DELBA frame using the normal access
1050  mechanisms. */
1051  AcIndex ac = QosUtilsMapTidToAc (hdr.GetQosTid ());
1052  m_edcaListeners[ac]->BlockAckInactivityTimeout (hdr.GetAddr2 (), hdr.GetQosTid ());
1053  return;
1054  }
1055  else if (hdr.IsQosData () && hdr.IsQosNoAck ())
1056  {
1057  if (ampduSubframe)
1058  {
1059  NS_LOG_DEBUG ("rx Ampdu with No Ack Policy from=" << hdr.GetAddr2 ());
1060  }
1061  else
1062  {
1063  NS_LOG_DEBUG ("rx unicast/noAck from=" << hdr.GetAddr2 ());
1064  }
1065  }
1066  else if (hdr.IsData () || hdr.IsMgt ())
1067  {
1068  if (hdr.IsMgt() && ampduSubframe)
1069  {
1070  NS_FATAL_ERROR ("Received management packet as part of an A-MPDU");
1071  }
1072  else
1073  {
1074  NS_LOG_DEBUG ("rx unicast/sendAck from=" << hdr.GetAddr2 ());
1077  &MacLow::SendAckAfterData, this,
1078  hdr.GetAddr2 (),
1079  hdr.GetDuration (),
1080  txVector.GetMode (),
1081  rxSnr);
1082  }
1083  }
1084  goto rxPacket;
1085  }
1086  else if (hdr.GetAddr1 ().IsGroup ())
1087  {
1088  if (ampduSubframe)
1089  {
1090  NS_FATAL_ERROR ("Received group addressed packet as part of an A-MPDU");
1091  }
1092  else
1093  {
1094  if (hdr.IsData () || hdr.IsMgt ())
1095  {
1096  NS_LOG_DEBUG ("rx group from=" << hdr.GetAddr2 ());
1097  m_receivedAtLeastOneMpdu = false;
1098  goto rxPacket;
1099  }
1100  else
1101  {
1102  // DROP
1103  }
1104  }
1105  }
1106  else if (m_promisc)
1107  {
1108  NS_ASSERT (hdr.GetAddr1 () != m_self);
1109  if (hdr.IsData ())
1110  {
1111  goto rxPacket;
1112  }
1113  }
1114  else
1115  {
1116  //NS_LOG_DEBUG_VERBOSE ("rx not-for-me from %d", GetSource (packet));
1117  }
1118  return;
1119 rxPacket:
1120  WifiMacTrailer fcs;
1121  packet->RemoveTrailer (fcs);
1122  m_rxCallback (packet, &hdr);
1123  return;
1124 }
1125 
1126 uint8_t
1128 {
1129  uint8_t tid = 0;
1130  if (hdr.IsQosData ())
1131  tid = hdr.GetQosTid ();
1132  else if (hdr.IsBlockAckReq ())
1133  {
1134  CtrlBAckRequestHeader baReqHdr;
1135  packet->PeekHeader (baReqHdr);
1136  tid = baReqHdr.GetTidInfo();
1137  }
1138  else if (hdr.IsBlockAck ())
1139  {
1140  CtrlBAckResponseHeader baRespHdr;
1141  packet->PeekHeader (baRespHdr);
1142  tid = baRespHdr.GetTidInfo ();
1143  }
1144  return tid;
1145 }
1146 
1147 uint32_t
1149 {
1150  WifiMacHeader ack;
1151  ack.SetType (WIFI_MAC_CTL_ACK);
1152  return ack.GetSize () + 4;
1153 }
1154 uint32_t
1156 {
1157  WifiMacHeader hdr;
1159  CtrlBAckResponseHeader blockAck;
1160  if (type == BASIC_BLOCK_ACK)
1161  {
1162  blockAck.SetType (BASIC_BLOCK_ACK);
1163  }
1164  else if (type == COMPRESSED_BLOCK_ACK)
1165  {
1166  blockAck.SetType (COMPRESSED_BLOCK_ACK);
1167  }
1168  else if (type == MULTI_TID_BLOCK_ACK)
1169  {
1170  //Not implemented
1171  NS_ASSERT (false);
1172  }
1173  return hdr.GetSize () + blockAck.GetSerializedSize () + 4;
1174 }
1175 uint32_t
1177 {
1178  WifiMacHeader rts;
1179  rts.SetType (WIFI_MAC_CTL_RTS);
1180  return rts.GetSize () + 4;
1181 }
1182 Time
1184 {
1185  WifiTxVector ackTxVector = GetAckTxVectorForData (to, dataTxVector.GetMode ());
1186  return GetAckDuration (ackTxVector);
1187 }
1188 Time
1190 {
1191  NS_ASSERT (ackTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); // ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
1192  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, WIFI_PREAMBLE_LONG, m_phy->GetFrequency(), 0, 0);
1193 }
1194 Time
1195 MacLow::GetBlockAckDuration (Mac48Address to, WifiTxVector blockAckReqTxVector, enum BlockAckType type) const
1196 {
1197  /*
1198  * For immediate Basic BlockAck we should transmit the frame with the same WifiMode
1199  * as the BlockAckReq.
1200  */
1201  WifiPreamble preamble;
1202  if (blockAckReqTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT && type == BASIC_BLOCK_ACK)
1203  preamble= WIFI_PREAMBLE_HT_MF;
1204  else
1205  preamble=WIFI_PREAMBLE_LONG;
1206  return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1207 }
1208 Time
1210 {
1211  WifiTxVector ctsTxVector = GetCtsTxVectorForRts (to, rtsTxVector.GetMode ());
1212  return GetCtsDuration (ctsTxVector);
1213 }
1214 
1215 Time
1217 {
1218  NS_ASSERT (ctsTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); // CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1219  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, WIFI_PREAMBLE_LONG, m_phy->GetFrequency(), 0, 0);
1220 }
1221 uint32_t
1223 {
1224  WifiMacHeader cts;
1225  cts.SetType (WIFI_MAC_CTL_CTS);
1226  return cts.GetSize () + 4;
1227 }
1228 uint32_t
1230 {
1231  uint32_t size;
1232  WifiMacTrailer fcs;
1233  if (m_ampdu)
1234  size = packet->GetSize ();
1235  else
1236  size= packet->GetSize () + hdr->GetSize () + fcs.GetSerializedSize ();
1237  return size;
1238 }
1239 
1242 {
1243  return m_stationManager->GetCtsToSelfTxVector (hdr, packet);
1244 }
1245 
1248 {
1249  Mac48Address to = hdr->GetAddr1 ();
1250  return m_stationManager->GetRtsTxVector (to, hdr, packet);
1251 }
1254 {
1255  Mac48Address to = hdr->GetAddr1 ();
1256  WifiMacTrailer fcs;
1257  uint32_t size = packet->GetSize ()+ hdr->GetSize () + fcs.GetSerializedSize ();
1258  //size is not used in anything!! will not worry about aggregation
1259  return m_stationManager->GetDataTxVector (to, hdr, packet, size);
1260 }
1263 {
1264  return m_stationManager->GetCtsTxVector (to, rtsTxMode);
1265 }
1268 {
1269  return m_stationManager->GetAckTxVector (to, dataTxMode);
1270 }
1273 {
1274  return m_stationManager->GetBlockAckTxVector (to, dataTxMode);
1275 }
1276 
1279 {
1280  return GetCtsTxVector (to, rtsTxMode);
1281 }
1284 {
1285  return GetAckTxVector (to, dataTxMode);
1286 }
1287 
1288 
1289 Time
1291  const WifiMacHeader* hdr,
1292  const MacLowTransmissionParameters& params) const
1293 {
1294  WifiPreamble preamble;
1295  Time txTime = Seconds (0);
1296  if (params.MustSendRts ())
1297  {
1298  WifiTxVector rtsTxVector = GetRtsTxVector (packet, hdr);
1299  //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
1301  {
1302  preamble = WIFI_PREAMBLE_HT_GF;
1303  }
1304  else
1305  {
1306  //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1307  preamble = WIFI_PREAMBLE_LONG;
1308  }
1309  txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1310  txTime += GetCtsDuration (hdr->GetAddr1 (), rtsTxVector);
1311  txTime += Time (GetSifs () * 2);
1312  }
1313  WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
1315  preamble = WIFI_PREAMBLE_HT_GF;
1316  else //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1317  preamble = WIFI_PREAMBLE_LONG;
1318  uint32_t dataSize = GetSize (packet, hdr);
1319  txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1320  if (params.MustWaitAck ())
1321  {
1322  txTime += GetSifs ();
1323  txTime += GetAckDuration (hdr->GetAddr1 (), dataTxVector);
1324  }
1325  return txTime;
1326 }
1327 
1328 Time
1330  const WifiMacHeader* hdr,
1331  const MacLowTransmissionParameters& params) const
1332 {
1333  Time txTime = CalculateOverallTxTime (packet, hdr, params);
1334  if (params.HasNextPacket ())
1335  {
1336  WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
1337  WifiPreamble preamble;
1338  //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
1340  preamble= WIFI_PREAMBLE_HT_GF;
1341  else if (dataTxVector.GetMode().GetModulationClass () == WIFI_MOD_CLASS_HT)
1342  preamble= WIFI_PREAMBLE_HT_MF;
1343  else
1344  preamble=WIFI_PREAMBLE_LONG;
1345  txTime += GetSifs ();
1346  txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1347  }
1348  return txTime;
1349 }
1350 
1351 void
1353 {
1355  Time duration = hdr.GetDuration ();
1356 
1357  if (hdr.IsCfpoll ()
1358  && hdr.GetAddr2 () == m_bssid)
1359  {
1360  // see section 9.3.2.2 802.11-1999
1361  DoNavResetNow (duration);
1362  return;
1363  }
1366  else if (hdr.GetAddr1 () != m_self)
1367  {
1368  // see section 9.2.5.4 802.11-1999
1369  bool navUpdated = DoNavStartNow (duration);
1370  if (hdr.IsRts () && navUpdated)
1371  {
1380  WifiMacHeader cts;
1381  cts.SetType (WIFI_MAC_CTL_CTS);
1382  WifiTxVector txVector=GetRtsTxVector (packet, &hdr);
1383  Time navCounterResetCtsMissedDelay =
1384  m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, preamble, m_phy->GetFrequency(), 0, 0) +
1385  Time (2 * GetSifs ()) + Time (2 * GetSlotTime ());
1386  m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
1388  Simulator::Now ());
1389  }
1390  }
1391 }
1392 
1393 void
1395 {
1396  if (m_phy->GetLastRxStartTime () < rtsEndRxTime)
1397  {
1398  DoNavResetNow (Seconds (0.0));
1399  }
1400 }
1401 
1402 void
1404 {
1405  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1406  {
1407  (*i)->NavReset (duration);
1408  }
1410  m_lastNavStart = duration;
1411 }
1412 bool
1414 {
1415  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1416  {
1417  (*i)->NavStart (duration);
1418  }
1419  Time newNavEnd = Simulator::Now () + duration;
1420  Time oldNavEnd = m_lastNavStart + m_lastNavDuration;
1421  if (newNavEnd > oldNavEnd)
1422  {
1424  m_lastNavDuration = duration;
1425  return true;
1426  }
1427  return false;
1428 }
1429 void
1431 {
1432  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1433  {
1434  (*i)->AckTimeoutStart (duration);
1435  }
1436 }
1437 void
1439 {
1440  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1441  {
1442  (*i)->AckTimeoutReset ();
1443  }
1444 }
1445 void
1447 {
1448  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1449  {
1450  (*i)->CtsTimeoutStart (duration);
1451  }
1452 }
1453 void
1455 {
1456  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
1457  {
1458  (*i)->CtsTimeoutReset ();
1459  }
1460 }
1461 
1462 void
1464  WifiTxVector txVector, WifiPreamble preamble)
1465 {
1466  NS_LOG_FUNCTION (this << packet << hdr << txVector);
1467  NS_LOG_DEBUG ("send " << hdr->GetTypeString () <<
1468  ", to=" << hdr->GetAddr1 () <<
1469  ", size=" << packet->GetSize () <<
1470  ", mode=" << txVector.GetMode () <<
1471  ", duration=" << hdr->GetDuration () <<
1472  ", seq=0x" << std::hex << m_currentHdr.GetSequenceControl () << std::dec);
1473  if (!m_ampdu || hdr->IsRts ())
1474  {
1475  m_phy->SendPacket (packet, txVector, preamble, 0);
1476  }
1477  else
1478  {
1479  Ptr<Packet> newPacket;
1480  Ptr <const Packet> dequeuedPacket;
1481  WifiMacHeader newHdr;
1482  WifiMacTrailer fcs;
1483  uint32_t queueSize = m_aggregateQueue->GetSize ();
1484  bool last = false;
1485  uint8_t packetType = 0;
1486  //Add packet tag
1487  AmpduTag ampdutag;
1488  ampdutag.SetAmpdu (true);
1489  Time delay = Seconds (0);
1490  for ( ; queueSize > 0; queueSize--)
1491  {
1492  dequeuedPacket = m_aggregateQueue->Dequeue (&newHdr);
1493  newPacket = dequeuedPacket->Copy ();
1494  newHdr.SetDuration (hdr->GetDuration ());
1495  newPacket->AddHeader (newHdr);
1496  newPacket->AddTrailer (fcs);
1497  if (queueSize == 1)
1498  {
1499  last = true;
1500  packetType = 2;
1501  }
1502  m_mpduAggregator->AddHeaderAndPad (newPacket, last);
1503 
1504  ampdutag.SetNoOfMpdus(queueSize);
1505  newPacket->AddPacketTag(ampdutag);
1506  if (delay == Seconds (0))
1507  {
1508  NS_LOG_DEBUG("Sending MPDU as part of A-MPDU");
1509  packetType = 1;
1510  m_phy->SendPacket (newPacket, txVector, preamble, packetType);
1511  }
1512  else
1513  {
1514  Simulator::Schedule (delay, &MacLow::SendPacket, this, newPacket, txVector, preamble, packetType);
1515  }
1516  if(queueSize > 1)
1517  delay = delay + m_phy->CalculateTxDuration (GetSize (newPacket, &newHdr), txVector, preamble, m_phy->GetFrequency(), packetType, 0);
1518  preamble = WIFI_PREAMBLE_NONE;
1519  }
1520  }
1521 }
1522 
1523 void
1524 MacLow::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType)
1525 {
1526  NS_LOG_DEBUG("Sending MPDU as part of A-MPDU");
1527  m_phy->SendPacket (packet, txVector, preamble, packetType);
1528 }
1529 
1530 void
1532 {
1533  NS_LOG_FUNCTION (this);
1534  NS_LOG_DEBUG ("cts timeout");
1539  if(m_sentMpdus == 0)
1540  {
1541  m_currentPacket = 0;
1542  }
1544  m_listener = 0;
1545  m_sentMpdus = 0;
1546  m_ampdu = false;
1547  listener->MissedCts ();
1548 }
1549 void
1551 {
1552  NS_LOG_FUNCTION (this);
1553  NS_LOG_DEBUG ("normal ack timeout");
1559  m_listener = 0;
1560  m_sentMpdus = 0;
1561  m_ampdu = false;
1563  listener->MissedAck ();
1564 }
1565 void
1567 {
1568  NS_LOG_FUNCTION (this);
1571  m_listener = 0;
1572  if (m_phy->IsStateIdle ())
1573  {
1574  NS_LOG_DEBUG ("fast Ack idle missed");
1575  listener->MissedAck ();
1576  }
1577  else
1578  {
1579  NS_LOG_DEBUG ("fast Ack ok");
1580  }
1581 }
1582 void
1584 {
1585  NS_LOG_FUNCTION (this);
1586  NS_LOG_DEBUG ("block ack timeout");
1587 
1590  m_listener = 0;
1591  m_sentMpdus = 0;
1592  m_ampdu = false;
1594  listener->MissedBlockAck ();
1595 }
1596 void
1598 {
1599  NS_LOG_FUNCTION (this);
1602  m_listener = 0;
1603  if (m_phy->IsStateIdle ())
1604  {
1605  NS_LOG_DEBUG ("super fast Ack failed");
1606  listener->MissedAck ();
1607  }
1608  else
1609  {
1610  NS_LOG_DEBUG ("super fast Ack ok");
1611  listener->GotAck (0.0, WifiMode ());
1612  }
1613 }
1614 
1615 void
1617 {
1618  NS_LOG_FUNCTION (this);
1619  /* send an RTS for this packet. */
1620  WifiMacHeader rts;
1621  rts.SetType (WIFI_MAC_CTL_RTS);
1622  rts.SetDsNotFrom ();
1623  rts.SetDsNotTo ();
1624  rts.SetNoRetry ();
1625  rts.SetNoMoreFragments ();
1626  rts.SetAddr1 (m_currentHdr.GetAddr1 ());
1627  rts.SetAddr2 (m_self);
1629  Time duration = Seconds (0);
1630 
1631  WifiPreamble preamble;
1632  //standard says RTS packets can have GF format sec 9.6.0e.1 page 110 bullet b 2
1634  preamble= WIFI_PREAMBLE_HT_GF;
1635  else //Otherwise, RTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1636  preamble = WIFI_PREAMBLE_LONG;
1637 
1638  if (m_txParams.HasDurationId ())
1639  {
1640  duration += m_txParams.GetDurationId ();
1641  }
1642  else
1643  {
1645  duration += GetSifs ();
1646  duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxVector);
1647  duration += GetSifs ();
1649  dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1650  duration += GetSifs ();
1652  {
1653  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2(), dataTxVector.GetMode ());
1654  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
1655  }
1657  {
1658  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2(), dataTxVector.GetMode ());
1659  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1660  }
1661  else if (m_txParams.MustWaitAck ())
1662  {
1663  duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
1664  }
1665  if (m_txParams.HasNextPacket ())
1666  {
1668  dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1669  if (m_txParams.MustWaitAck ())
1670  {
1671  duration += GetSifs ();
1672  duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
1673  }
1674  }
1675  }
1676  rts.SetDuration (duration);
1677 
1678  Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1679  Time timerDelay = txDuration + GetCtsTimeout ();
1680 
1682  NotifyCtsTimeoutStartNow (timerDelay);
1684 
1685  Ptr<Packet> packet = Create<Packet> ();
1686  packet->AddHeader (rts);
1687  WifiMacTrailer fcs;
1688  packet->AddTrailer (fcs);
1689 
1690  ForwardDown (packet, &rts, rtsTxVector,preamble);
1691 }
1692 
1693 void
1695 {
1696  WifiPreamble preamble;
1697 
1698  //Since it is data then it can have format = GF
1700  preamble = WIFI_PREAMBLE_HT_GF;
1701  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1702  preamble = WIFI_PREAMBLE_HT_MF;
1703  else
1704  preamble = WIFI_PREAMBLE_LONG;
1705 
1706  Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1708  {
1709  Time timerDelay = txDuration + GetAckTimeout ();
1711  NotifyAckTimeoutStartNow (timerDelay);
1713  }
1714  else if (m_txParams.MustWaitFastAck ())
1715  {
1716  Time timerDelay = txDuration + GetPifs ();
1718  NotifyAckTimeoutStartNow (timerDelay);
1720  }
1721  else if (m_txParams.MustWaitSuperFastAck ())
1722  {
1723  Time timerDelay = txDuration + GetPifs ();
1725  NotifyAckTimeoutStartNow (timerDelay);
1728  }
1729  else if (m_txParams.MustWaitBasicBlockAck ())
1730  {
1731  Time timerDelay = txDuration + GetBasicBlockAckTimeout ();
1733  NotifyAckTimeoutStartNow (timerDelay);
1735  }
1737  {
1738  Time timerDelay = txDuration + GetCompressedBlockAckTimeout ();
1740  NotifyAckTimeoutStartNow (timerDelay);
1742  }
1743  else if (m_txParams.HasNextPacket ())
1744  {
1746  {
1747  Time delay = txDuration + GetRifs ();
1750  }
1751  else
1752  {
1753  Time delay = txDuration + GetSifs ();
1756  }
1757  }
1758  else
1759  {
1760  // since we do not expect any timer to be triggered.
1761  Simulator::Schedule(txDuration, &MacLow::EndTxNoAck, this);
1762  }
1763 }
1764 
1765 void
1767 {
1768  NS_LOG_FUNCTION (this);
1769  /* send this packet directly. No RTS is needed. */
1771  WifiPreamble preamble;
1772 
1774  //In the future has to make sure that receiver has greenfield enabled
1775  preamble = WIFI_PREAMBLE_HT_GF;
1776  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1777  preamble = WIFI_PREAMBLE_HT_MF;
1778  else
1779  preamble = WIFI_PREAMBLE_LONG;
1780 
1781  StartDataTxTimers (dataTxVector);
1782 
1783  Time duration = Seconds (0.0);
1784  if (m_txParams.HasDurationId ())
1785  {
1786  duration += m_txParams.GetDurationId ();
1787  }
1788  else
1789  {
1791  {
1792  duration += GetSifs ();
1793  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
1794  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
1795  }
1797  {
1798  duration += GetSifs ();
1799  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
1800  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1801  }
1802  else if (m_txParams.MustWaitAck ())
1803  {
1804  duration += GetSifs ();
1805  duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
1806  }
1807  if (m_txParams.HasNextPacket ())
1808  {
1809  duration += GetSifs ();
1811  dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1812  if (m_txParams.MustWaitAck ())
1813  {
1814  duration += GetSifs ();
1815  duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
1816  }
1817  }
1818  }
1819  m_currentHdr.SetDuration (duration);
1820 
1821  if (!m_ampdu)
1822  {
1824  WifiMacTrailer fcs;
1825  m_currentPacket->AddTrailer (fcs);
1826  }
1827 
1828  ForwardDown (m_currentPacket, &m_currentHdr, dataTxVector, preamble);
1829  m_currentPacket = 0;
1830 }
1831 
1832 bool
1833 MacLow::IsNavZero (void) const
1834 {
1836  {
1837  return true;
1838  }
1839  else
1840  {
1841  return false;
1842  }
1843 }
1844 void
1846 {
1847  WifiMacHeader cts;
1848  cts.SetType (WIFI_MAC_CTL_CTS);
1849  cts.SetDsNotFrom ();
1850  cts.SetDsNotTo ();
1851  cts.SetNoMoreFragments ();
1852  cts.SetNoRetry ();
1853  cts.SetAddr1 (m_self);
1854 
1856 
1857  WifiPreamble preamble;
1858  if (ctsTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1859  preamble = WIFI_PREAMBLE_HT_MF;
1860  else
1861  preamble = WIFI_PREAMBLE_LONG;
1862 
1863  Time duration = Seconds (0);
1864 
1865  if (m_txParams.HasDurationId ())
1866  {
1867  duration += m_txParams.GetDurationId ();
1868  }
1869  else
1870  {
1872  duration += GetSifs ();
1874  dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1876  {
1877 
1878  duration += GetSifs ();
1879  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
1880  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
1881  }
1883  {
1884  duration += GetSifs ();
1885  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
1886  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1887  }
1888  else if (m_txParams.MustWaitAck ())
1889  {
1890  duration += GetSifs ();
1891  duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
1892  }
1893  if (m_txParams.HasNextPacket ())
1894  {
1895  duration += GetSifs ();
1897  dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1899  {
1900  duration += GetSifs ();
1901  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
1902  duration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1903  }
1904  else if (m_txParams.MustWaitAck ())
1905  {
1906  duration += GetSifs ();
1907  duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
1908  }
1909  }
1910  }
1911 
1912  cts.SetDuration (duration);
1913 
1914  Ptr<Packet> packet = Create<Packet> ();
1915  packet->AddHeader (cts);
1916  WifiMacTrailer fcs;
1917  packet->AddTrailer (fcs);
1918 
1919  ForwardDown (packet, &cts, ctsTxVector,preamble);
1920 
1921  Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency(), 0, 0);
1922  txDuration += GetSifs ();
1924 
1925  m_sendDataEvent = Simulator::Schedule (txDuration,
1926  &MacLow::SendDataAfterCts, this,
1927  cts.GetAddr1 (),
1928  duration);
1929 }
1930 void
1931 MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
1932 {
1933  NS_LOG_FUNCTION (this << source << duration << rtsTxVector.GetMode () << rtsSnr);
1934  /* send a CTS when you receive a RTS
1935  * right after SIFS.
1936  */
1937  WifiTxVector ctsTxVector = GetCtsTxVector (source, rtsTxVector.GetMode ());
1938  WifiMacHeader cts;
1939  cts.SetType (WIFI_MAC_CTL_CTS);
1940  cts.SetDsNotFrom ();
1941  cts.SetDsNotTo ();
1942  cts.SetNoMoreFragments ();
1943  cts.SetNoRetry ();
1944  cts.SetAddr1 (source);
1945  duration -= GetCtsDuration (source, rtsTxVector);
1946  duration -= GetSifs ();
1947  NS_ASSERT (duration >= MicroSeconds (0));
1948  cts.SetDuration (duration);
1949 
1950  Ptr<Packet> packet = Create<Packet> ();
1951  packet->AddHeader (cts);
1952  WifiMacTrailer fcs;
1953  packet->AddTrailer (fcs);
1954 
1955  SnrTag tag;
1956  tag.Set (rtsSnr);
1957  packet->AddPacketTag (tag);
1958 
1959  //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1960  ForwardDown (packet, &cts, ctsTxVector, WIFI_PREAMBLE_LONG);
1961 }
1962 
1963 void
1965 {
1966  NS_LOG_FUNCTION (this);
1967  /* send the third step in a
1968  * RTS/CTS/DATA/ACK hanshake
1969  */
1970  NS_ASSERT (m_currentPacket != 0);
1972 
1973  if (m_aggregateQueue->GetSize () != 0)
1974  {
1975  for (std::vector<Item>::size_type i = 0; i != m_txPackets.size(); i++)
1976  {
1977  uint8_t tid = GetTid (m_txPackets.at(i).packet, m_txPackets.at(i).hdr);
1978  AcIndex ac = QosUtilsMapTidToAc (tid);
1979  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt= m_edcaListeners.find(ac);
1980 
1981  listenerIt->second->CompleteMpduTx (m_txPackets.at(i).packet, m_txPackets.at(i).hdr, m_txPackets.at(i).timestamp);
1982  }
1983  m_txPackets.clear ();
1984  }
1985 
1986  WifiPreamble preamble;
1988  //In the future has to make sure that receiver has greenfield enabled
1989  preamble = WIFI_PREAMBLE_HT_GF;
1990  else if (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
1991  preamble = WIFI_PREAMBLE_HT_MF;
1992  else
1993  preamble = WIFI_PREAMBLE_LONG;
1994 
1995  StartDataTxTimers (dataTxVector);
1996  Time newDuration = Seconds (0);
1998  {
1999  newDuration += GetSifs ();
2000  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
2001  newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, BASIC_BLOCK_ACK);
2002  }
2004  {
2005  newDuration += GetSifs ();
2006  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
2007  newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2008  }
2009  else if (m_txParams.MustWaitAck ())
2010  {
2011  newDuration += GetSifs ();
2012  newDuration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
2013  }
2014  if (m_txParams.HasNextPacket ())
2015  {
2016  newDuration += GetSifs ();
2017  newDuration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (), dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
2019  {
2020  newDuration += GetSifs ();
2021  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_currentHdr.GetAddr2 (), dataTxVector.GetMode ());
2022  newDuration += GetBlockAckDuration (m_currentHdr.GetAddr1 (), blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2023  }
2024  else if (m_txParams.MustWaitAck ())
2025  {
2026  newDuration += GetSifs ();
2027  newDuration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector);
2028  }
2029  }
2030 
2031  Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr),dataTxVector, preamble, m_phy->GetFrequency(), 0, 0);
2032  duration -= txDuration;
2033  duration -= GetSifs ();
2034 
2035  duration = std::max (duration, newDuration);
2036  NS_ASSERT (duration >= MicroSeconds (0));
2037  m_currentHdr.SetDuration (duration);
2038 
2039  if (!m_ampdu)
2040  {
2042  WifiMacTrailer fcs;
2043  m_currentPacket->AddTrailer (fcs);
2044  }
2045 
2046  ForwardDown (m_currentPacket, &m_currentHdr, dataTxVector,preamble);
2047  m_currentPacket = 0;
2048 }
2049 
2050 void
2052 {
2053  m_listener->StartNext ();
2054 }
2055 
2056 void
2058 {
2060  m_listener = 0;
2061  listener->EndTxNoAck ();
2062 }
2063 
2064 void
2066 {
2067  NS_LOG_FUNCTION (this);
2069  m_listener = 0;
2070  listener->MissedAck ();
2071  NS_LOG_DEBUG ("fast Ack busy but missed");
2072 }
2073 
2074 void
2075 MacLow::SendAckAfterData (Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
2076 {
2077  NS_LOG_FUNCTION (this);
2078  /* send an ACK when you receive
2079  * a packet after SIFS.
2080  */
2081  WifiTxVector ackTxVector = GetAckTxVector (source, dataTxMode);
2082  WifiMacHeader ack;
2083  ack.SetType (WIFI_MAC_CTL_ACK);
2084  ack.SetDsNotFrom ();
2085  ack.SetDsNotTo ();
2086  ack.SetNoRetry ();
2087  ack.SetNoMoreFragments ();
2088  ack.SetAddr1 (source);
2089  duration -= GetAckDuration (ackTxVector);
2090  duration -= GetSifs ();
2091  NS_ASSERT (duration >= MicroSeconds (0));
2092  ack.SetDuration (duration);
2093 
2094  Ptr<Packet> packet = Create<Packet> ();
2095  packet->AddHeader (ack);
2096  WifiMacTrailer fcs;
2097  packet->AddTrailer (fcs);
2098 
2099  SnrTag tag;
2100  tag.Set (dataSnr);
2101  packet->AddPacketTag (tag);
2102 
2103  //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
2104  ForwardDown (packet, &ack, ackTxVector, WIFI_PREAMBLE_LONG);
2105 }
2106 
2107 bool
2108 MacLow::IsInWindow (uint16_t seq, uint16_t winstart, uint16_t winsize)
2109 {
2110  return ((seq - winstart+ 4096) % 4096) < winsize;
2111 }
2112 
2113 bool
2115  {
2117  {
2118  Mac48Address originator = hdr.GetAddr2 ();
2119  uint8_t tid = 0;
2120  if (hdr.IsQosData ())
2121  tid = hdr.GetQosTid ();
2122  uint16_t seqNumber = hdr.GetSequenceNumber ();
2123  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2124  if (it != m_bAckAgreements.end ())
2125  {
2126  //Implement HT immediate Block Ack support for HT Delayed Block Ack is not added yet
2127  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), seqNumber))
2128  {
2129  StoreMpduIfNeeded (packet, hdr);
2130  if (!IsInWindow(hdr.GetSequenceNumber (), (*it).second.first.GetStartingSequence (), (*it).second.first.GetBufferSize ()))
2131  {
2132  uint16_t delta = (seqNumber - (*it).second.first.GetWinEnd()+ 4096) % 4096;
2133  if (delta > 1)
2134  {
2135  (*it).second.first.SetWinEnd (seqNumber);
2136  int16_t winEnd = (*it).second.first.GetWinEnd ();
2137  int16_t bufferSize = (*it).second.first.GetBufferSize ();
2138  uint16_t sum = ((uint16_t)(std::abs(winEnd - bufferSize + 1))) % 4096;
2139  (*it).second.first.SetStartingSequence (sum);
2140  RxCompleteBufferedPacketsWithSmallerSequence ((*it).second.first.GetStartingSequence (), originator, tid);
2141  }
2142  }
2143  RxCompleteBufferedPacketsUntilFirstLost (originator, tid); //forwards up packets starting from winstart and set winstart to last +1
2144  (*it).second.first.SetWinEnd(((*it).second.first.GetStartingSequence()+(*it).second.first.GetBufferSize()-1)%4096);
2145  }
2146  return true;
2147  }
2148  return false;
2149  }
2150  else
2151  return StoreMpduIfNeeded (packet,hdr);
2152 }
2153 
2154 bool
2156 {
2157  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2158  if (it != m_bAckAgreements.end ())
2159  {
2160  WifiMacTrailer fcs;
2161  packet->RemoveTrailer (fcs);
2162  BufferedPacket bufferedPacket (packet, hdr);
2163 
2164  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2165  uint16_t mappedSeqControl = QosUtilsMapSeqControlToUniqueInteger (hdr.GetSequenceControl (), endSequence);
2166 
2167  BufferedPacketI i = (*it).second.second.begin ();
2168  for (; i != (*it).second.second.end ()
2169  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceControl (), endSequence) < mappedSeqControl; i++)
2170  {
2171  ;
2172  }
2173  (*it).second.second.insert (i, bufferedPacket);
2174 
2175  //Update block ack cache
2176  BlockAckCachesI j = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2177  NS_ASSERT (j != m_bAckCaches.end ());
2178  (*j).second.UpdateWithMpdu (&hdr);
2179  return true;
2180  }
2181  return false;
2182 }
2183 
2184 void
2186  uint16_t startingSeq)
2187 {
2188  uint8_t tid = respHdr->GetTid ();
2189  BlockAckAgreement agreement (originator, tid);
2190  if (respHdr->IsImmediateBlockAck ())
2191  {
2192  agreement.SetImmediateBlockAck ();
2193  }
2194  else
2195  {
2196  agreement.SetDelayedBlockAck ();
2197  }
2198  agreement.SetAmsduSupport (respHdr->IsAmsduSupported ());
2199  agreement.SetBufferSize (respHdr->GetBufferSize () + 1);
2200  agreement.SetTimeout (respHdr->GetTimeout ());
2201  agreement.SetStartingSequence (startingSeq);
2202 
2203  std::list<BufferedPacket> buffer (0);
2204  AgreementKey key (originator, respHdr->GetTid ());
2205  AgreementValue value (agreement, buffer);
2206  m_bAckAgreements.insert (std::make_pair (key, value));
2207 
2208  BlockAckCache cache;
2209  cache.Init (startingSeq, respHdr->GetBufferSize () + 1);
2210  m_bAckCaches.insert (std::make_pair (key, cache));
2211 
2212  if (respHdr->GetTimeout () != 0)
2213  {
2214  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, respHdr->GetTid ()));
2215  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2216 
2217  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2218 
2219  it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
2221  m_edcaListeners[ac],
2222  originator, tid);
2223  }
2224 }
2225 
2226 void
2228 {
2229  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2230  if (it != m_bAckAgreements.end ())
2231  {
2232  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequence (), originator, tid);
2233  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2234  m_bAckAgreements.erase (it);
2235 
2236  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2237  NS_ASSERT (i != m_bAckCaches.end ());
2238  m_bAckCaches.erase (i);
2239  }
2240 }
2241 
2242 void
2244 {
2245  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2246  if (it != m_bAckAgreements.end ())
2247  {
2248  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2249  uint16_t mappedStart = QosUtilsMapSeqControlToUniqueInteger (seq, endSequence);
2250  BufferedPacketI last = (*it).second.second.begin ();
2251  uint16_t guard = 0;
2252  if (last != (*it).second.second.end ())
2253  {
2254  guard = (*it).second.second.begin ()->second.GetSequenceControl () & 0xfff0;
2255  }
2256  BufferedPacketI i = (*it).second.second.begin ();
2257  for (; i != (*it).second.second.end ()
2258  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceNumber (), endSequence) < mappedStart;)
2259  {
2260  if (guard == (*i).second.GetSequenceControl ())
2261  {
2262  if (!(*i).second.IsMoreFragments ())
2263  {
2264  while (last != i)
2265  {
2266  m_rxCallback ((*last).first, &(*last).second);
2267  last++;
2268  }
2269  m_rxCallback ((*last).first, &(*last).second);
2270  last++;
2271  /* go to next packet */
2272  while (i != (*it).second.second.end () && ((guard >> 4) & 0x0fff) == (*i).second.GetSequenceNumber ())
2273  {
2274  i++;
2275  }
2276  if (i != (*it).second.second.end ())
2277  {
2278  guard = (*i).second.GetSequenceControl () & 0xfff0;
2279  last = i;
2280  }
2281  }
2282  else
2283  {
2284  guard++;
2285  }
2286  }
2287  else
2288  {
2289  /* go to next packet */
2290  while (i != (*it).second.second.end () && ((guard >> 4) & 0x0fff) == (*i).second.GetSequenceNumber ())
2291  {
2292  i++;
2293  }
2294  if (i != (*it).second.second.end ())
2295  {
2296  guard = (*i).second.GetSequenceControl () & 0xfff0;
2297  last = i;
2298  }
2299  }
2300  }
2301  (*it).second.second.erase ((*it).second.second.begin (), i);
2302  }
2303 }
2304 
2305 void
2307 {
2308  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2309  if (it != m_bAckAgreements.end ())
2310  {
2311  uint16_t startingSeqCtrl = ((*it).second.first.GetStartingSequence () << 4) & 0xfff0;
2312  uint16_t guard = startingSeqCtrl;
2313 
2314  BufferedPacketI lastComplete = (*it).second.second.begin ();
2315  BufferedPacketI i = (*it).second.second.begin ();
2316  for (; i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl (); i++)
2317  {
2318  if (!(*i).second.IsMoreFragments ())
2319  {
2320  while (lastComplete != i)
2321  {
2322  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2323  lastComplete++;
2324  }
2325  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2326  lastComplete++;
2327  }
2328  guard = (*i).second.IsMoreFragments () ? (guard + 1) : ((guard + 16) & 0xfff0);
2329  }
2330  (*it).second.first.SetStartingSequence ((guard >> 4) & 0x0fff);
2331  /* All packets already forwarded to WifiMac must be removed from buffer:
2332  [begin (), lastComplete) */
2333  (*it).second.second.erase ((*it).second.second.begin (), lastComplete);
2334  }
2335 }
2336 void
2337 MacLow::SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate,
2338  Time duration, WifiMode blockAckReqTxMode)
2339 {
2340  Ptr<Packet> packet = Create<Packet> ();
2341  packet->AddHeader (*blockAck);
2342 
2343  WifiMacHeader hdr;
2345  hdr.SetAddr1 (originator);
2346  hdr.SetAddr2 (GetAddress ());
2347  hdr.SetDsNotFrom ();
2348  hdr.SetDsNotTo ();
2349  hdr.SetNoRetry ();
2350  hdr.SetNoMoreFragments ();
2351 
2352  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (originator, blockAckReqTxMode);
2353 
2354  m_currentPacket = packet;
2355  m_currentHdr = hdr;
2356  if (immediate)
2357  {
2359  duration -= GetSifs ();
2360  if (blockAck->IsBasic ())
2361  {
2362  duration -= GetBlockAckDuration (originator, blockAckReqTxVector, BASIC_BLOCK_ACK);
2363  }
2364  else if (blockAck->IsCompressed ())
2365  {
2366  duration -= GetBlockAckDuration (originator, blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2367  }
2368  else if (blockAck->IsMultiTid ())
2369  {
2370  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2371  }
2372  }
2373  else
2374  {
2375  m_txParams.EnableAck ();
2376  duration += GetSifs ();
2377  duration += GetAckDuration (originator, blockAckReqTxVector);
2378  }
2380 
2381  if (!immediate)
2382  {
2383  StartDataTxTimers (blockAckReqTxVector);
2384  }
2385 
2386  NS_ASSERT (duration >= MicroSeconds (0));
2387  hdr.SetDuration (duration);
2388  //here should be present a control about immediate or delayed block ack
2389  //for now we assume immediate
2390  packet->AddHeader (hdr);
2391  WifiMacTrailer fcs;
2392  packet->AddTrailer (fcs);
2393  WifiPreamble preamble;
2394  if (blockAckReqTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT)
2395  preamble = WIFI_PREAMBLE_HT_MF;
2396  else
2397  preamble = WIFI_PREAMBLE_LONG;
2398  ForwardDown (packet, &hdr, blockAckReqTxVector, preamble);
2399  m_currentPacket = 0;
2400 }
2401 void
2402 MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector)
2403 {
2404  NS_LOG_FUNCTION (this);
2405  CtrlBAckResponseHeader blockAck;
2406  uint16_t seqNumber = 0;
2407  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2408  NS_ASSERT (i != m_bAckCaches.end ());
2409  seqNumber = (*i).second.GetWinStart ();
2410 
2411  bool immediate = true;
2412  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2413  blockAck.SetStartingSequence (seqNumber);
2414  blockAck.SetTidInfo (tid);
2415  immediate = (*it).second.first.IsImmediateBlockAck ();
2416  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2417  NS_LOG_DEBUG ("Got Implicit block Ack Req with seq " << seqNumber);
2418  (*i).second.FillBlockAckBitmap (&blockAck);
2419 
2420  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxVector.GetMode ());
2421 }
2422 
2423 void
2425  Time duration, WifiMode blockAckReqTxMode)
2426 {
2427  NS_LOG_FUNCTION (this);
2428  CtrlBAckResponseHeader blockAck;
2429  uint8_t tid = 0;
2430  bool immediate = false;
2431  if (!reqHdr.IsMultiTid ())
2432  {
2433  tid = reqHdr.GetTidInfo ();
2434  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2435  if (it != m_bAckAgreements.end ())
2436  {
2437  blockAck.SetStartingSequence (reqHdr.GetStartingSequence ());
2438  blockAck.SetTidInfo (tid);
2439  immediate = (*it).second.first.IsImmediateBlockAck ();
2440  if (reqHdr.IsBasic ())
2441  {
2442  blockAck.SetType (BASIC_BLOCK_ACK);
2443  }
2444  else if (reqHdr.IsCompressed ())
2445  {
2446  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2447  }
2448  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2449  NS_ASSERT (i != m_bAckCaches.end ());
2450  (*i).second.FillBlockAckBitmap (&blockAck);
2451  NS_LOG_DEBUG ("Got block Ack Req with seq " << reqHdr.GetStartingSequence ());
2452 
2454  {
2455  /* All packets with smaller sequence than starting sequence control must be passed up to Wifimac
2456  * See 9.10.3 in IEEE 802.11e standard.
2457  */
2459  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2460  }
2461  else
2462  {
2463  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence(), reqHdr.GetStartingSequence ()))
2464  {
2465  (*it).second.first.SetStartingSequence(reqHdr.GetStartingSequence ());
2466  (*it).second.first.SetWinEnd(((*it).second.first.GetStartingSequence()+(*it).second.first.GetBufferSize()-1) % 4096);
2468  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2469  (*it).second.first.SetWinEnd(((*it).second.first.GetStartingSequence()+(*it).second.first.GetBufferSize()-1) % 4096);
2470  }
2471  }
2472  }
2473  else
2474  {
2475  NS_LOG_DEBUG ("there's not a valid block ack agreement with " << originator);
2476  }
2477  }
2478  else
2479  {
2480  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2481  }
2482 
2483  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode);
2484 }
2485 
2486 void
2488 {
2489  if (agreement.GetTimeout () != 0)
2490  {
2491  NS_ASSERT (agreement.m_inactivityEvent.IsRunning ());
2492  agreement.m_inactivityEvent.Cancel ();
2493  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2494  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2495  //std::map<AcIndex, MacLowTransmissionListener*>::iterator it = m_edcaListeners.find (ac);
2496  //NS_ASSERT (it != m_edcaListeners.end ());
2497 
2498  agreement.m_inactivityEvent = Simulator::Schedule (timeout,
2500  m_edcaListeners[ac],
2501  agreement.GetPeer (),
2502  agreement.GetTid ());
2503  }
2504 }
2505 
2506 void
2508 {
2509  m_edcaListeners.insert (std::make_pair (ac, listener));
2510 }
2511 
2512 void
2514 {
2515  m_mpduAggregator = aggregator;
2516 }
2517 
2518 void
2519 MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiTxVector txVector, WifiPreamble preamble)
2520 {
2521  m_currentTxVector = txVector;
2522  AmpduTag ampdu;
2523  bool normalAck = false;
2524  bool ampduSubframe = false;
2525  if (aggregatedPacket->RemovePacketTag(ampdu))
2526  {
2527  ampduSubframe = true;
2529  MpduAggregator::DeaggregatedMpdusCI n = packets.begin ();
2530 
2531  WifiMacHeader firsthdr;
2532  (*n).first->PeekHeader(firsthdr);
2533  NS_LOG_DEBUG ("duration/id=" << firsthdr.GetDuration ());
2534  NotifyNav ((*n).first, firsthdr, preamble);
2535  if (firsthdr.GetAddr1 () == m_self)
2536  {
2537  m_receivedAtLeastOneMpdu = true;
2538  if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ())
2539  ReceiveOk ((*n).first, rxSnr, txVector, preamble, ampduSubframe);
2540  else if (firsthdr.IsData () || firsthdr.IsQosData ())
2541  {
2542  NS_LOG_DEBUG ("Deaagregate packet with sequence=" << firsthdr.GetSequenceNumber ());
2543  ReceiveOk ((*n).first, rxSnr, txVector, preamble, ampduSubframe);
2544  if (firsthdr.IsQosAck ())
2545  {
2546  NS_LOG_DEBUG ("Normal Ack");
2547  normalAck = true;
2548  }
2549  }
2550  else
2551  NS_FATAL_ERROR ("Received A-MPDU with invalid first MPDU type");
2552  }
2553 
2554  if (normalAck && (ampdu.GetNoOfMpdus () == 1))
2555  {
2556  //send block Ack
2557  if (firsthdr.IsBlockAckReq ())
2558  {
2559  NS_FATAL_ERROR ("Sending a BlockAckReq with QosPolicy equal to Normal Ack");
2560  }
2561  uint8_t tid = firsthdr.GetQosTid ();
2562  AgreementsI it = m_bAckAgreements.find (std::make_pair (firsthdr.GetAddr2 (), tid));
2563  if (it != m_bAckAgreements.end ())
2564  {
2566  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
2567  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
2568  NS_LOG_DEBUG ("rx A-MPDU/sendImmediateBlockAck from=" << firsthdr.GetAddr2 ());
2571  firsthdr.GetQosTid(),
2572  firsthdr.GetAddr2 (),
2573  firsthdr.GetDuration (),
2574  txVector);
2575  }
2576  else
2577  {
2578  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
2579  }
2580  m_receivedAtLeastOneMpdu = false;
2581  }
2582  }
2583  else
2584  {
2585  ReceiveOk (aggregatedPacket,rxSnr, txVector, preamble, ampduSubframe);
2586  }
2587 }
2588 
2589 bool
2590 MacLow::StopMpduAggregation(Ptr<const Packet> peekedPacket, WifiMacHeader peekedHdr, Ptr<Packet> aggregatedPacket, uint16_t size) const
2591 {
2592  WifiPreamble preamble;
2595  preamble = WIFI_PREAMBLE_HT_GF;
2596  else //Block ACK following implicit BAR always use non-HT PPDU
2597  preamble = WIFI_PREAMBLE_LONG;
2598 
2599  if (peekedPacket == 0)
2600  return true;
2601 
2602  //An HT STA shall not transmit a PPDU that has a duration that is greater than aPPDUMaxTime (10 milliseconds)
2603  if(m_phy->CalculateTxDuration (aggregatedPacket->GetSize () + peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, dataTxVector, preamble, m_phy->GetFrequency(), 0, 0) > MilliSeconds(10))
2604  return true;
2605 
2606  if (!m_mpduAggregator->CanBeAggregated (peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, aggregatedPacket, size))
2607  return true;
2608 
2609  return false;
2610 }
2611 
2614 {
2615  NS_ASSERT (m_aggregateQueue->GetSize () == 0);
2616  bool isAmpdu = false;
2617  Ptr<Packet> newPacket, tempPacket;
2618  WifiMacHeader peekedHdr;
2619  newPacket = packet->Copy();
2620  //missing hdr.IsAck() since we have no means of knowing the Tid of the Ack yet
2621  if (hdr.IsQosData() || hdr.IsBlockAck()|| hdr.IsBlockAckReq())
2622  {
2623  Time tstamp;
2624  uint8_t tid = GetTid (packet, hdr);
2625  Ptr<WifiMacQueue> queue;
2626  AcIndex ac = QosUtilsMapTidToAc (tid);
2627  //since a blockack agreement always preceeds mpdu aggregation there should always exist blockAck listener
2628  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt= m_edcaListeners.find(ac);
2629  NS_ASSERT (listenerIt != m_edcaListeners.end ());
2630  queue = listenerIt->second->GetQueue();
2631 
2632  if (!hdr.GetAddr1 ().IsBroadcast () && m_mpduAggregator!= 0)
2633  {
2634  //Have to make sure that their exist a block Ack agreement before sending an AMPDU (BlockAck Manager)
2635  if (listenerIt->second->GetBlockAckAgreementExists (hdr.GetAddr1(), tid))
2636  {
2637  /* here is performed mpdu aggregation */
2638  /* MSDU aggregation happened in edca if the user asked for it so m_currentPacket may contains a normal packet or a A-MSDU*/
2639  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
2640  peekedHdr = hdr;
2641  uint16_t startingSequenceNumber = 0;
2642  uint16_t currentSequenceNumber = 0;
2643  uint8_t qosPolicy = 0;
2644  uint16_t blockAckSize = 0;
2645  bool aggregated = false;
2646  int i = 0;
2647  Ptr<Packet> aggPacket = newPacket->Copy ();
2648 
2649  if (!hdr.IsBlockAckReq())
2650  {
2651  if (!hdr.IsBlockAck())
2652  {
2653  startingSequenceNumber = peekedHdr.GetSequenceNumber();
2654  peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
2655  }
2656  currentSequenceNumber = peekedHdr.GetSequenceNumber();
2657  newPacket->AddHeader (peekedHdr);
2658  WifiMacTrailer fcs;
2659  newPacket->AddTrailer (fcs);
2660 
2661  aggregated=m_mpduAggregator->Aggregate (newPacket, currentAggregatedPacket);
2662 
2663  if (aggregated)
2664  {
2665  NS_LOG_DEBUG ("Adding packet with Sequence number " << peekedHdr.GetSequenceNumber()<<" to A-MPDU, packet size = " << newPacket->GetSize ()<< ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
2666  i++;
2667  m_sentMpdus++;
2668  m_aggregateQueue->Enqueue (aggPacket, peekedHdr);
2669  }
2670  }
2671  else if (hdr.IsBlockAckReq())
2672  {
2673  blockAckSize = packet->GetSize() + hdr.GetSize() + WIFI_MAC_FCS_LENGTH;
2674  qosPolicy = 3; //if the last subrame is block ack req then set ack policy of all frames to blockack
2675  CtrlBAckRequestHeader blockAckReq;
2676  packet->PeekHeader (blockAckReq);
2677  startingSequenceNumber = blockAckReq.GetStartingSequence ();
2678  }
2679  aggregated = false;
2680  bool retry = false;
2681  //looks for other packets to the same destination with the same Tid need to extend that to include MSDUs
2682  Ptr<const Packet> peekedPacket = listenerIt->second->PeekNextPacketInBaQueue (peekedHdr, peekedHdr.GetAddr1 (), tid, &tstamp);
2683  if (peekedPacket == 0)
2684  {
2685  peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
2687  hdr.GetAddr1 (), &tstamp);
2688  currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr);
2689 
2690  /* here is performed MSDU aggregation (two-level aggregation) */
2691  if (peekedPacket != 0 && listenerIt->second->GetMsduAggregator () != 0)
2692  {
2693  tempPacket = PerformMsduAggregation(peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
2694  if (tempPacket != 0) //MSDU aggregation
2695  peekedPacket = tempPacket->Copy();
2696  }
2697  }
2698  else
2699  {
2700  retry = true;
2701  currentSequenceNumber = peekedHdr.GetSequenceNumber();
2702  }
2703 
2704  while (IsInWindow (currentSequenceNumber, startingSequenceNumber, 64) && !StopMpduAggregation (peekedPacket, peekedHdr, currentAggregatedPacket, blockAckSize))
2705  {
2706  //for now always send AMPDU with normal ACK
2707  if (retry == false)
2708  {
2709  currentSequenceNumber = listenerIt->second->GetNextSequenceNumberfor (&peekedHdr);
2710  peekedHdr.SetSequenceNumber (currentSequenceNumber);
2711  peekedHdr.SetFragmentNumber (0);
2712  peekedHdr.SetNoMoreFragments ();
2713  peekedHdr.SetNoRetry ();
2714  }
2715  if (qosPolicy == 0)
2716  peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
2717  else
2718  peekedHdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK);
2719 
2720  newPacket = peekedPacket->Copy ();
2721  Ptr<Packet> aggPacket = newPacket->Copy ();
2722 
2723  newPacket->AddHeader (peekedHdr);
2724  WifiMacTrailer fcs;
2725  newPacket->AddTrailer (fcs);
2726  aggregated = m_mpduAggregator->Aggregate (newPacket, currentAggregatedPacket);
2727  if (aggregated)
2728  {
2729  m_aggregateQueue->Enqueue (aggPacket, peekedHdr);
2730  if (i == 1 && hdr.IsQosData ())
2731  {
2732  if (!m_txParams.MustSendRts ())
2733  {
2734  listenerIt->second->CompleteMpduTx (packet, hdr, tstamp);
2735  }
2736  else
2737  {
2738  InsertInTxQueue (packet, hdr, tstamp);
2739  }
2740  }
2741  NS_LOG_DEBUG ("Adding packet with Sequence number " << peekedHdr.GetSequenceNumber()<<" to A-MPDU, packet size = " << newPacket->GetSize ()<< ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
2742  i++;
2743  isAmpdu = true;
2744  m_sentMpdus++;
2745  if (!m_txParams.MustSendRts ())
2746  {
2747  listenerIt->second->CompleteMpduTx (peekedPacket, peekedHdr, tstamp);
2748  }
2749  else
2750  {
2751  InsertInTxQueue (peekedPacket, peekedHdr, tstamp);
2752  }
2753  if (retry)
2754  listenerIt->second->RemoveFromBaQueue(tid, hdr.GetAddr1 (), peekedHdr.GetSequenceNumber ());
2755  else
2756  queue->Remove (peekedPacket);
2757  newPacket = 0;
2758  }
2759  else
2760  break;
2761  if (retry == true)
2762  {
2763  peekedPacket = listenerIt->second->PeekNextPacketInBaQueue(peekedHdr, hdr.GetAddr1(), tid, &tstamp);
2764  if (peekedPacket == 0)
2765  {
2766  //I reached the first packet that I added to this A-MPDU
2767  retry = false;
2768  peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
2769  WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp);
2770  if (peekedPacket != 0)
2771  {
2772  //find what will the sequence number be so that we don't send more than 64 packets apart
2773  currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr);
2774 
2775  if (listenerIt->second->GetMsduAggregator () != 0)
2776  {
2777  tempPacket = PerformMsduAggregation(peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
2778  if (tempPacket != 0) //MSDU aggregation
2779  peekedPacket = tempPacket->Copy();
2780  }
2781  }
2782  }
2783  else
2784  currentSequenceNumber = peekedHdr.GetSequenceNumber();
2785  }
2786  else
2787  {
2788  peekedPacket = queue->PeekByTidAndAddress (&peekedHdr, tid,
2789  WifiMacHeader::ADDR1, hdr.GetAddr1 (), &tstamp);
2790  if (peekedPacket != 0)
2791  {
2792  //find what will the sequence number be so that we don't send more than 64 packets apart
2793  currentSequenceNumber = listenerIt->second->PeekNextSequenceNumberfor (&peekedHdr);
2794 
2795  if (listenerIt->second->GetMsduAggregator () != 0 && IsInWindow (currentSequenceNumber, startingSequenceNumber, 64))
2796  {
2797  tempPacket = PerformMsduAggregation(peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
2798  if (tempPacket != 0) //MSDU aggregation
2799  peekedPacket = tempPacket->Copy();
2800  }
2801  }
2802  }
2803  }
2804  if (isAmpdu)
2805  {
2806  if (hdr.IsBlockAckReq())
2807  {
2808  newPacket = packet->Copy();
2809  peekedHdr = hdr;
2810  Ptr<Packet> aggPacket = newPacket->Copy();
2811  m_aggregateQueue->Enqueue (aggPacket, peekedHdr);
2812  newPacket->AddHeader (peekedHdr);
2813  WifiMacTrailer fcs;
2814  newPacket->AddTrailer (fcs);
2815  m_mpduAggregator->Aggregate (newPacket, currentAggregatedPacket);
2816  }
2817  if (qosPolicy==0)
2818  {
2819  listenerIt->second->CompleteTransfer(hdr.GetAddr1 (),tid);
2820  }
2821  //Add packet tag
2822  AmpduTag ampdutag;
2823  ampdutag.SetAmpdu (true);
2824  ampdutag.SetNoOfMpdus(i);
2825  newPacket = currentAggregatedPacket;
2826  newPacket->AddPacketTag(ampdutag);
2827  currentAggregatedPacket = 0;
2828  NS_LOG_DEBUG ("tx unicast A-MPDU");
2829  listenerIt->second->SetAmpdu(true);
2830  }
2831  else
2832  {
2833  uint32_t queueSize = m_aggregateQueue->GetSize ();
2834  NS_ASSERT (queueSize <= 2); //since it is not an A-MPDU then only 2 packets should have been added to the queue no more
2835  if (queueSize >= 1)
2836  {
2837  //remove any packets that we added to the aggregate queue
2839  }
2840  }
2841  }
2842  }
2843  }
2844  return newPacket;
2845 }
2846 
2847 void
2849 {
2850  NS_LOG_DEBUG("Flush aggregate queue");
2851  m_aggregateQueue->Flush ();
2852  m_txPackets.clear ();
2853 }
2854 
2855 void
2857 {
2858  Item item;
2859 
2860  item.packet = packet;
2861  item.hdr = hdr;
2862  item.timestamp = tStamp;
2863 
2864  m_txPackets.push_back (item);
2865 }
2866 
2868 MacLow::PerformMsduAggregation(Ptr<const Packet> packet, WifiMacHeader *hdr, Time *tstamp, Ptr<Packet> currentAmpduPacket, uint16_t blockAckSize)
2869 {
2870  bool msduAggregation = false;
2871  bool isAmsdu = false;
2872  Ptr<Packet> currentAmsduPacket = Create<Packet> ();
2873  Ptr<Packet> tempPacket = Create<Packet> ();
2874 
2875  Ptr<WifiMacQueue> queue;
2876  AcIndex ac = QosUtilsMapTidToAc (GetTid (packet, *hdr));
2877  std::map<AcIndex, MacLowAggregationCapableTransmissionListener*>::const_iterator listenerIt= m_edcaListeners.find(ac);
2878  NS_ASSERT (listenerIt != m_edcaListeners.end ());
2879  queue = listenerIt->second->GetQueue();
2880 
2881  listenerIt->second->GetMsduAggregator ()->Aggregate (packet, currentAmsduPacket,
2882  listenerIt->second->GetSrcAddressForAggregation (*hdr),
2883  listenerIt->second->GetDestAddressForAggregation (*hdr));
2884 
2885  Ptr<const Packet> peekedPacket = queue->PeekByTidAndAddress (hdr, hdr->GetQosTid (),
2886  WifiMacHeader::ADDR1, hdr->GetAddr1 (), tstamp);
2887  while (peekedPacket != 0)
2888  {
2889  tempPacket = currentAmsduPacket;
2890 
2891  msduAggregation = listenerIt->second->GetMsduAggregator ()->Aggregate (peekedPacket, tempPacket,
2892  listenerIt->second->GetSrcAddressForAggregation (*hdr),
2893  listenerIt->second->GetDestAddressForAggregation (*hdr));
2894 
2895  if (msduAggregation && !StopMpduAggregation (tempPacket, *hdr, currentAmpduPacket, blockAckSize))
2896  {
2897  isAmsdu = true;
2898  currentAmsduPacket = tempPacket;
2899  queue->Remove (peekedPacket);
2900  }
2901  else
2902  {
2903  break;
2904  }
2905  peekedPacket = queue->PeekByTidAndAddress (hdr, hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 (), tstamp);
2906  }
2907 
2908  if (isAmsdu)
2909  {
2910  NS_LOG_DEBUG ("A-MSDU with size = " << currentAmsduPacket->GetSize ());
2911  hdr->SetQosAmsdu ();
2912  hdr->SetAddr3 (GetBssid ());
2913  return currentAmsduPacket;
2914  }
2915  else
2916  {
2917  return 0;
2918  }
2919 }
2920 
2921 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
void Set(double snr)
Set the SNR to the given value.
Definition: snr-tag.cc:84
bool MustSendRts(void) const
Definition: mac-low.cc:242
Time GetPifs(void) const
Return PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:639
uint32_t GetAckSize(void) const
Return the total ACK size (including FCS trailer).
Definition: mac-low.cc:1148
virtual ~MacLowDcfListener()
Definition: mac-low.cc:68
void SetPifs(Time pifs)
Set PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:579
Time m_ctsTimeout
CTS timeout duration.
Definition: mac-low.h:1325
uint16_t GetBufferSize(void) const
Return the buffer size.
Definition: mgt-headers.cc:993
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:1311
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 "...
Ptr< WifiPhy > GetPhy(void) const
Definition: mac-low.cc:515
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:2487
bool GetGreenfieldSupported(Mac48Address address) const
Return whether the station supports Greenfield or not.
enum ns3::MacLowTransmissionParameters::@89 m_waitAck
EventId m_blockAckTimeoutEvent
Block ACK timeout event.
Definition: mac-low.h:1304
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:1195
Callback template class.
Definition: callback.h:984
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:53
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:1189
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:100
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:594
EventId m_waitSifsEvent
Wait for SIFS event.
Definition: mac-low.h:1309
void DoNavResetNow(Time duration)
Reset NAV with the given duration.
Definition: mac-low.cc:1403
virtual Mac48Address GetDestAddressForAggregation(const WifiMacHeader &hdr)
Definition: mac-low.cc:129
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:649
bool m_receivedAtLeastOneMpdu
Flag whether an MPDU has already been successfully received while receiving an A-MPDU.
Definition: mac-low.h:1363
void EnableBasicBlockAck(void)
Wait BASICBLOCKACKTimeout for a Basic Block Ack Response frame.
Definition: mac-low.cc:167
Mac48Address GetPeer(void) const
Return the peer address.
EventId m_fastAckTimeoutEvent
Fast ACK timeout event.
Definition: mac-low.h:1301
Time m_pifs
PCF Interframe Space (PIFS) duration.
Definition: mac-low.h:1328
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:836
bool DoNavStartNow(Time duration)
Start NAV with the given duration.
Definition: mac-low.cc:1413
void FastAckFailedTimeout(void)
Event handler when fast ACK timeout occurs (busy).
Definition: mac-low.cc:2065
Mac48Address GetBssid(void) const
Return the Basic Service Set Identification.
Definition: mac-low.cc:644
void SetSifs(Time sifs)
Set Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:569
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:1345
enum WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:115
WifiTxVector GetCtsToSelfTxVector(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return a TXVECTOR for the CTS-to-self frame.
Definition: mac-low.cc:1241
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.
Definition: mgt-headers.cc:981
void RegisterBlockAckListenerForAc(enum AcIndex ac, MacLowAggregationCapableTransmissionListener *listener)
Definition: mac-low.cc:2507
void SetupPhyMacLowListener(Ptr< WifiPhy > phy)
Set up WifiPhy listener for this MacLow.
Definition: mac-low.cc:388
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:329
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:874
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:766
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:812
uint8_t GetTid(Ptr< const Packet > packet, const WifiMacHeader hdr) const
Definition: mac-low.cc:1127
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:247
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)
Fatal error handling.
Definition: fatal-error.h:100
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:86
DcfListeners m_dcfListeners
List of MacLowDcfListener (pass events to Dcf)
Definition: mac-low.h:1298
uint8_t m_sentMpdus
Number of transmitted MPDUs in an A-MPDU that have not been acknowledged yet.
Definition: mac-low.h:1360
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:1335
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:655
void DeaggregateAmpduAndReceive(Ptr< Packet > aggregatedPacket, double rxSnr, WifiTxVector txVector, WifiPreamble preamble)
Definition: mac-low.cc:2519
Time GetCompressedBlockAckTimeout() const
Return Compressed Block ACK timeout of this MacLow.
Definition: mac-low.cc:614
Callback< R > MakeNullCallback(void)
Definition: callback.h:1442
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:819
Mac48Address m_bssid
BSSID address (Mac48Address)
Definition: mac-low.h:1321
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:30
Ptr< Packet > AggregateToAmpdu(Ptr< const Packet > packet, const WifiMacHeader hdr)
Definition: mac-low.cc:2613
EventId m_sendCtsEvent
Event to send CTS.
Definition: mac-low.h:1306
MacLowRxCallback m_rxCallback
Callback to pass packet up.
Definition: mac-low.h:1278
Time GetCtsTimeout(void) const
Return CTS timeout of this MacLow.
Definition: mac-low.cc:619
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:1302
EventId m_sendAckEvent
Event to send ACK.
Definition: mac-low.h:1307
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:93
Time GetCtsDuration(WifiTxVector ctsTxVector) const
Return the time required to transmit the CTS (including preamble and FCS).
Definition: mac-low.cc:1216
bool MustWaitFastAck(void) const
Definition: mac-low.cc:217
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:2868
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:2051
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:1293
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:82
void SetCtsToSelfSupported(bool enable)
Enable or disable CTS-to-self capability.
Definition: mac-low.cc:554
void NormalAckTimeout(void)
Event handler when normal ACK timeout occurs.
Definition: mac-low.cc:1550
void SetBasicBlockAckTimeout(Time blockAckTimeout)
Set Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:544
bool IsAmsduSupported(void) const
Return whether A-MSDU capability is supported.
Definition: mgt-headers.cc:999
void SetNoOfMpdus(uint8_t noofmpdus)
Definition: ampdu-tag.cc:61
BlockAckCaches m_bAckCaches
Definition: mac-low.h:1355
void InsertInTxQueue(Ptr< const Packet > packet, const WifiMacHeader &hdr, Time tStamp)
Insert in a temporary queue.
Definition: mac-low.cc:2856
virtual bool IsStateIdle(void)=0
virtual uint32_t GetNRetryNeededPackets(Mac48Address recipient, uint8_t tid) const
Definition: mac-low.cc:114
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:395
virtual void GotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address source, WifiMode txMode)
Definition: mac-low.cc:57
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
Definition: wifi-preamble.h:29
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:105
WifiTxVector m_currentTxVector
TXVECTOR used for the current packet transmission.
Definition: mac-low.h:1362
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
void DestroyBlockAckAgreement(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2227
Time m_lastNavDuration
The duration of the latest NAV.
Definition: mac-low.h:1332
virtual uint32_t GetSerializedSize(void) const
std::pair< Ptr< Packet >, WifiMacHeader > BufferedPacket
Definition: mac-low.h:1342
void SendCtsToSelf(void)
Send CTS for a CTS-to-self mechanism.
Definition: mac-low.cc:1845
bool m_ctsToSelfSupported
Flag whether CTS-to-self is supported.
Definition: mac-low.h:1359
void SetAmpdu(bool supported)
Set m_ampdu to 1.
Definition: ampdu-tag.cc:55
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:2075
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual Mac48Address GetSrcAddressForAggregation(const WifiMacHeader &hdr)
Definition: mac-low.cc:124
void CreateBlockAckAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address originator, uint16_t startingSeq)
Definition: mac-low.cc:2185
Ptr< WifiMacQueue > m_aggregateQueue
Queue used for MPDU aggregation.
Definition: mac-low.h:1361
void NotifyNav(Ptr< const Packet > packet, const WifiMacHeader &hdr, WifiPreamble preamble)
Definition: mac-low.cc:1352
virtual void NotifyTxStart(Time duration, double txPowerDbm)
Definition: mac-low.cc:332
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:1155
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:308
virtual void NotifyWakeup(void)
Notify listeners that we woke up.
Definition: mac-low.cc:346
receive notifications about phy events.
Definition: wifi-phy.h:44
void CtsTimeout(void)
Event handler when CTS timeout occurs.
Definition: mac-low.cc:1531
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:2057
std::map< AgreementKey, BlockAckCache >::iterator BlockAckCachesI
Definition: mac-low.h:1352
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:1267
void SetAckTimeout(Time ackTimeout)
Set ACK timeout of this MacLow.
Definition: mac-low.cc:539
virtual uint32_t GetNOutstandingPackets(Mac48Address recipient, uint8_t tid)
Definition: mac-low.cc:109
virtual void SendPacket(Ptr< const Packet > packet, WifiTxVector txvector, enum WifiPreamble preamble, uint8_t packetType)=0
virtual void GotCts(double snr, WifiMode txMode)=0
void SendDataAfterCts(Mac48Address source, Time duration)
Send DATA after receiving CTS.
Definition: mac-low.cc:1964
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:27
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:2337
Time GetRifs(void) const
Return Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:629
HT PHY (Clause 20)
Definition: wifi-mode.h:56
virtual void NotifyRxStart(Time duration)
Definition: mac-low.cc:323
virtual void NotifySleep(void)
Notify listeners that we went to sleep.
Definition: mac-low.cc:342
void NavCounterResetCtsMissed(Time rtsEndRxTime)
Reset NAV after CTS was missed when the NAV was setted with RTS.
Definition: mac-low.cc:1394
Ptr< WifiRemoteStationManager > m_stationManager
Pointer to WifiRemoteStationManager (rate control)
Definition: mac-low.h:1277
bool MustWaitMultiTidBlockAck(void) const
Definition: mac-low.cc:237
Headers for Block ack response.
Definition: ctrl-headers.h:183
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1296
Mac48Address GetAddress(void) const
Return the MAC address of this MacLow.
Definition: mac-low.cc:599
uint32_t GetNextPacketSize(void) const
Definition: mac-low.cc:263
Agreements m_bAckAgreements
Definition: mac-low.h:1354
bool HasNextPacket(void) const
Definition: mac-low.cc:258
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:35
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:1283
void SendBlockAckAfterAmpdu(uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector)
Invoked after an A-MPDU has been received.
Definition: mac-low.cc:2402
Time CalculateTxDuration(uint32_t size, WifiTxVector txvector, enum WifiPreamble preamble, double frequency, uint8_t packetType, uint8_t incFlag)
Definition: wifi-phy.cc:577
virtual uint16_t GetNextSequenceNumberfor(WifiMacHeader *hdr)
Return the next sequence number for the given header.
Definition: mac-low.cc:90
void RegisterDcfListener(MacLowDcfListener *listener)
Definition: mac-low.cc:660
virtual uint32_t GetSerializedSize(void) const
void NotifySwitchingStartNow(Time duration)
Definition: mac-low.cc:796
Time m_slotTime
Slot duration.
Definition: mac-low.h:1327
bool m_promisc
Flag if the device is operating in promiscuous mode.
Definition: mac-low.h:1334
WifiMacHeader hdr
Definition: mac-low.h:1286
void CancelAllEvents(void)
Cancel all scheduled events.
Definition: mac-low.cc:435
virtual void StartTransmission(Ptr< const Packet > packet, const WifiMacHeader *hdr, MacLowTransmissionParameters parameters, MacLowTransmissionListener *listener)
Definition: mac-low.cc:683
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:1343
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:277
void BlockAckTimeout(void)
Event handler when block ACK timeout occurs.
Definition: mac-low.cc:1583
void NotifyCtsTimeoutStartNow(Time duration)
Notify DcfManager (via DcfListener) that CTS timer should be started for the given duration...
Definition: mac-low.cc:1446
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:2424
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:172
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SuperFastAckTimeout(void)
Event handler when super fast ACK timeout occurs.
Definition: mac-low.cc:1597
void SetBssid(Mac48Address ad)
Set the Basic Service Set Identification.
Definition: mac-low.cc:589
virtual void UnregisterListener(WifiPhyListener *listener)=0
uint32_t GetRtsSize(void) const
Return the total RTS size (including FCS trailer).
Definition: mac-low.cc:1176
void EnableAck(void)
Wait ACKTimeout for an ACK.
Definition: mac-low.cc:187
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:1329
EventId m_normalAckTimeoutEvent
Normal ACK timeout event.
Definition: mac-low.h:1300
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:1694
void AddTrailer(const Trailer &trailer)
Add trailer to this packet.
Definition: packet.cc:284
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:1454
bool MustWaitBasicBlockAck(void) const
Definition: mac-low.cc:227
bool MustWaitCompressedBlockAck(void) const
Definition: mac-low.cc:232
uint32_t RemoveTrailer(Trailer &trailer)
Remove a deserialized trailer from the internal buffer.
Definition: packet.cc:300
bool NeedCtsToSelf(void)
Check if CTS-to-self mechanism should be used for the current packet.
Definition: mac-low.cc:750
an EUI-48 address
Definition: mac48-address.h:43
Ptr< const Packet > packet
Definition: mac-low.h:1285
virtual void Cancel(void)=0
Invoked if this transmission was canceled one way or another.
Time m_ackTimeout
ACK timeout duration.
Definition: mac-low.h:1322
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: mac-low.cc:2108
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:1566
void DisableRts(void)
Do not send rts and wait for cts before sending data.
Definition: mac-low.cc:202
void EnableMultiTidBlockAck(void)
NOT IMPLEMENTED FOR NOW.
Definition: mac-low.cc:177
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:1305
void RxCompleteBufferedPacketsWithSmallerSequence(uint16_t seq, Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2243
void SendCtsAfterRts(Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
Send CTS after receiving RTS.
Definition: mac-low.cc:1931
void SetPhy(Ptr< WifiPhy > phy)
Set up WifiPhy associated with this MacLow.
Definition: mac-low.cc:507
virtual bool IsStateTx(void)=0
Time m_basicBlockAckTimeout
Basic block ACK timeout duration.
Definition: mac-low.h:1323
Time GetDurationId(void) const
Definition: mac-low.cc:252
uint16_t GetTimeout(void) const
Return the timeout.
Definition: mgt-headers.cc:987
uint8_t GetTid(void) const
Return the Traffic ID (TID).
Definition: mgt-headers.cc:975
virtual void MissedBlockAck(void)
ns3::MacLow did not receive an expected BLOCK_ACK within BlockAckTimeout.
Definition: mac-low.cc:61
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:86
Time m_sifs
Short Interframe Space (SIFS) duration.
Definition: mac-low.h:1326
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:756
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:634
void SetDelayedBlockAck(void)
Set Block ACK policy to delayed ACK.
Time m_lastNavStart
The time when the latest NAV started.
Definition: mac-low.h:1331
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:335
WifiTxVector GetRtsTxVector(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return a TXVECTOR for the RTS frame given the destination.
Definition: mac-low.cc:1247
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:1253
handle RTS/CTS/DATA/ACK transactions.
Definition: mac-low.h:486
virtual void MissedCts(void)=0
ns3::MacLow did not receive an expected CTS within CtsTimeout.
std::vector< Item > m_txPackets
Contain temporary items to be sent with the next A-MPDU transmission, once RTS/CTS exchange has succe...
Definition: mac-low.h:1364
EventId m_sendDataEvent
Event to send DATA.
Definition: mac-low.h:1308
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:2114
MacLowTransmissionParameters m_txParams
Transmission parameters of the current packet.
Definition: mac-low.h:1318
void SetRifs(Time rifs)
Set Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:584
virtual void DoDispose(void)
Destructor implementation.
Definition: mac-low.cc:406
void NotifyAckTimeoutResetNow()
Notify DcfManager (via DcfListener) that ACK timer should be resetted.
Definition: mac-low.cc:1438
bool MustWaitSuperFastAck(void) const
Definition: mac-low.cc:222
Time CalculateOverallTxTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &params) const
Definition: mac-low.cc:1290
QueueListeners m_edcaListeners
Definition: mac-low.h:1358
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:1272
bool IsData(void) const
Return true if the Type is DATA.
Mac48Address m_self
Address of this MacLow (Mac48Address)
Definition: mac-low.h:1320
Maintains information for a block ack agreement.
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS DATA...
EventId m_fastAckFailedTimeoutEvent
Fast ACK failed timeout event.
Definition: mac-low.h:1303
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:75
bool IsNavZero(void) const
Check if NAV is zero.
Definition: mac-low.cc:1833
void EnableRts(void)
Send a RTS, and wait CTSTimeout for a CTS.
Definition: mac-low.cc:197
void NotifyAckTimeoutStartNow(Time duration)
Notify DcfManager (via DcfListener) that ACK timer should be started for the given duration...
Definition: mac-low.cc:1430
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:574
Ptr< Packet > m_currentPacket
Current packet transmitted/to be transmitted.
Definition: mac-low.h:1316
Time GetSifs(void) const
Return Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:624
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:843
bool StopMpduAggregation(Ptr< const Packet > peekedPacket, WifiMacHeader peekedHdr, Ptr< Packet > aggregatedPacket, uint16_t size) const
Definition: mac-low.cc:2590
Implement the header for management frames of type add block ack response.
Definition: mgt-headers.h:572
ns3::MacLow * m_macLow
Definition: mac-low.cc:350
#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:866
std::map< AgreementKey, AgreementValue >::iterator AgreementsI
Definition: mac-low.h:1349
EventId m_endTxNoAckEvent
Event for finishing transmission that does not require ACK.
Definition: mac-low.h:1310
void SendPacket(Ptr< const Packet > packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType)
Forward the packet down to WifiPhy for transmission.
Definition: mac-low.cc:1524
WifiTxVector GetDataTxVector(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, uint32_t fullPacketSize)
void EnableOverrideDurationId(Time durationId)
Definition: mac-low.cc:152
virtual void SetReceiveOkCallback(RxOkCallback callback)=0
bool GetCtsToSelfSupported() const
Return whether CTS-to-self capability is supported.
Definition: mac-low.cc:559
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:827
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:564
void EnableNextData(uint32_t size)
Definition: mac-low.cc:142
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:157
Time GetAckTimeout(void) const
Return ACK timeout of this MacLow.
Definition: mac-low.cc:604
virtual Ptr< MsduAggregator > GetMsduAggregator(void) const
Definition: mac-low.cc:119
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:95
EventId m_waitRifsEvent
Wait for RIFS event.
Definition: mac-low.h:1312
void DisableNextData(void)
Do not attempt to send data burst after current transmission.
Definition: mac-low.cc:147
void SendDataPacket(void)
Send DATA packet, which can be DATA-ACK or RTS-CTS-DATA-ACK transaction.
Definition: mac-low.cc:1766
void SetTimeout(uint16_t timeout)
Set timeout.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:882
uint32_t GetCtsSize(void) const
Return the total CTS size (including FCS trailer).
Definition: mac-low.cc:1222
WifiMacHeader m_currentHdr
Header of the current packet.
Definition: mac-low.h:1317
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:534
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)
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:1463
PhyMacLowListener(ns3::MacLow *macLow)
Create a PhyMacLowListener for the given MacLow.
Definition: mac-low.cc:316
Time m_compressedBlockAckTimeout
Compressed block ACK timeout duration.
Definition: mac-low.h:1324
WifiMode GetMode(void) const
WifiTxVector GetBlockAckTxVector(Mac48Address address, WifiMode dataMode)
bool MustWaitAck(void) const
Definition: mac-low.cc:207
bool IsRts(void) const
Return true if the header is a RTS header.
Headers for Block ack request.
Definition: ctrl-headers.h:49
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:666
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:2848
virtual ~PhyMacLowListener()
Definition: mac-low.cc:320
void ResetPhy(void)
Remove WifiPhy associated with this MacLow.
Definition: mac-low.cc:520
void DisableAck(void)
Do not wait for Ack after data transmission.
Definition: mac-low.cc:192
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:1346
virtual void NotifySwitchingStart(Time duration)
Definition: mac-low.cc:338
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:1278
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
Time GetBasicBlockAckTimeout() const
Return Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:609
WifiTxVector GetAckTxVector(Mac48Address address, WifiMode dataMode)
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:1329
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:35
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:1262
uint8_t GetNoOfMpdus(void) const
Definition: ampdu-tag.cc:94
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:2155
bool MustWaitNormalAck(void) const
Definition: mac-low.cc:212
virtual bool GetGreenfield(void) const =0
virtual ~MacLow()
Definition: mac-low.cc:382
Ptr< MpduAggregator > m_mpduAggregator
Definition: mac-low.h:1314
A struct for packet, Wifi header, and timestamp.
Definition: mac-low.h:1283
Ptr< WifiPhy > m_phy
Pointer to WifiPhy (actually send/receives frames)
Definition: mac-low.h:1276
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
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:549
Implements the IEEE 802.11 MAC trailer.
virtual void AddHeaderAndPad(Ptr< Packet > packet, bool last)=0
Adds A-MPDU subframe header and padding to each MPDU that is part of an A-MPDU before it is sent...
virtual void NotifyRxEndOk(void)
We have received the last bit of a packet for which NotifyRxStart was invoked first and...
Definition: mac-low.cc:326
void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > manager)
Set up WifiRemoteStationManager associated with this MacLow.
Definition: mac-low.cc:528
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:1337
void SetMpduAggregator(Ptr< MpduAggregator > aggregator)
Set up MpduAggregator associated with this MacLow.
Definition: mac-low.cc:2513
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:1229
MacLowTransmissionListener * m_listener
Transmission listener for the current packet.
Definition: mac-low.h:1319
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:1616
void RxCompleteBufferedPacketsUntilFirstLost(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2306
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.