A Discrete-Event Network Simulator
API
mac-low.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 INRIA
4  * Copyright (c) 2009 MIRKO BANCHI
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  * Mirko Banchi <mk.banchi@gmail.com>
21  */
22 
23 #include "ns3/simulator.h"
24 #include "ns3/log.h"
25 #include "ns3/socket.h"
26 #include "mac-low.h"
27 #include "edca-txop-n.h"
28 #include "snr-tag.h"
29 #include "ampdu-tag.h"
30 #include "wifi-mac-queue.h"
31 #include "wifi-utils.h"
32 
33 #undef NS_LOG_APPEND_CONTEXT
34 #define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_self << "] "
35 
36 namespace ns3 {
37 
38 NS_LOG_COMPONENT_DEFINE ("MacLow");
39 
44 {
45 public:
52  : m_macLow (macLow)
53  {
54  }
55  virtual ~PhyMacLowListener ()
56  {
57  }
58  void NotifyRxStart (Time duration)
59  {
60  }
61  void NotifyRxEndOk (void)
62  {
63  }
64  void NotifyRxEndError (void)
65  {
66  }
67  void NotifyTxStart (Time duration, double txPowerDbm)
68  {
69  }
70  void NotifyMaybeCcaBusyStart (Time duration)
71  {
72  }
73  void NotifySwitchingStart (Time duration)
74  {
76  }
77  void NotifySleep (void)
78  {
80  }
81  void NotifyOff (void)
82  {
84  }
85  void NotifyWakeup (void)
86  {
87  }
88  void NotifyOn (void)
89  {
90  }
91 
92 private:
94 };
95 
96 
98  : m_normalAckTimeoutEvent (),
99  m_fastAckTimeoutEvent (),
100  m_superFastAckTimeoutEvent (),
101  m_fastAckFailedTimeoutEvent (),
102  m_blockAckTimeoutEvent (),
103  m_ctsTimeoutEvent (),
104  m_sendCtsEvent (),
105  m_sendAckEvent (),
106  m_sendDataEvent (),
107  m_waitIfsEvent (),
108  m_endTxNoAckEvent (),
109  m_currentPacket (0),
110  m_currentDca (0),
111  m_lastNavStart (Seconds (0)),
112  m_lastNavDuration (Seconds (0)),
113  m_promisc (false),
114  m_ampdu (false),
115  m_phyMacLowListener (0),
116  m_ctsToSelfSupported (false)
117 {
118  NS_LOG_FUNCTION (this);
119  for (uint8_t i = 0; i < 8; i++)
120  {
121  m_aggregateQueue[i] = CreateObject<WifiMacQueue> ();
122  }
123 }
124 
126 {
127  NS_LOG_FUNCTION (this);
128 }
129 
130 /* static */
131 TypeId
133 {
134  static TypeId tid = TypeId ("ns3::MacLow")
135  .SetParent<Object> ()
136  .SetGroupName ("Wifi")
137  .AddConstructor<MacLow> ()
138  ;
139  return tid;
140 }
141 
142 void
144 {
147 }
148 
149 void
151 {
152  if (m_phyMacLowListener != 0 )
153  {
155  delete m_phyMacLowListener;
157  }
158 }
159 
160 void
162 {
163  NS_LOG_FUNCTION (this);
175  m_phy = 0;
176  m_stationManager = 0;
177  if (m_phyMacLowListener != 0)
178  {
179  delete m_phyMacLowListener;
181  }
182  for (uint8_t i = 0; i < 8; i++)
183  {
184  m_aggregateQueue[i] = 0;
185  }
186  m_ampdu = false;
187 }
188 
189 void
191 {
192  NS_LOG_FUNCTION (this);
193  bool oneRunning = false;
195  {
197  oneRunning = true;
198  }
200  {
202  oneRunning = true;
203  }
205  {
207  oneRunning = true;
208  }
210  {
212  oneRunning = true;
213  }
215  {
217  oneRunning = true;
218  }
220  {
222  oneRunning = true;
223  }
224  if (m_sendCtsEvent.IsRunning ())
225  {
227  oneRunning = true;
228  }
229  if (m_sendAckEvent.IsRunning ())
230  {
232  oneRunning = true;
233  }
234  if (m_sendDataEvent.IsRunning ())
235  {
237  oneRunning = true;
238  }
239  if (m_waitIfsEvent.IsRunning ())
240  {
242  oneRunning = true;
243  }
245  {
247  oneRunning = true;
248  }
249  if (oneRunning && m_currentDca != 0)
250  {
251  m_currentDca->Cancel ();
252  m_currentDca = 0;
253  }
254 }
255 
256 void
258 {
259  m_phy = phy;
263 }
264 
266 MacLow::GetPhy (void) const
267 {
268  return m_phy;
269 }
270 
271 void
273 {
277  m_phy = 0;
278 }
279 
280 void
282 {
283  m_stationManager = manager;
284 }
285 
286 void
288 {
289  m_self = ad;
290 }
291 
292 void
294 {
295  m_ackTimeout = ackTimeout;
296 }
297 
298 void
300 {
301  m_basicBlockAckTimeout = blockAckTimeout;
302 }
303 
304 void
306 {
307  m_compressedBlockAckTimeout = blockAckTimeout;
308 }
309 
310 void
312 {
313  m_ctsToSelfSupported = enable;
314 }
315 
316 bool
318 {
319  return m_ctsToSelfSupported;
320 }
321 
322 void
324 {
325  m_ctsTimeout = ctsTimeout;
326 }
327 
328 void
330 {
331  m_sifs = sifs;
332 }
333 
334 void
336 {
337  m_slotTime = slotTime;
338 }
339 
340 void
342 {
343  m_pifs = pifs;
344 }
345 
346 void
348 {
349  m_rifs = rifs;
350 }
351 
352 void
354 {
355  m_bssid = bssid;
356 }
357 
358 void
360 {
361  m_promisc = true;
362 }
363 
365 MacLow::GetAddress (void) const
366 {
367  return m_self;
368 }
369 
370 Time
372 {
373  return m_ackTimeout;
374 }
375 
376 Time
378 {
379  return m_basicBlockAckTimeout;
380 }
381 
382 Time
384 {
386 }
387 
388 Time
390 {
391  return m_ctsTimeout;
392 }
393 
394 Time
395 MacLow::GetSifs (void) const
396 {
397  NS_LOG_FUNCTION (this);
398  return m_sifs;
399 }
400 
401 Time
402 MacLow::GetRifs (void) const
403 {
404  NS_LOG_FUNCTION (this);
405  return m_rifs;
406 }
407 
408 Time
410 {
411  return m_slotTime;
412 }
413 
414 Time
415 MacLow::GetPifs (void) const
416 {
417  return m_pifs;
418 }
419 
421 MacLow::GetBssid (void) const
422 {
423  return m_bssid;
424 }
425 
426 bool
427 MacLow::IsPromisc (void) const
428 {
429  return m_promisc;
430 }
431 
432 void
434 {
435  m_rxCallback = callback;
436 }
437 
438 void
440 {
441  m_dcfManagers.push_back (dcf);
442 }
443 
444 bool
446 {
447  uint32_t size, actualSize;
448  WifiMacTrailer fcs;
449  size = packet->GetSize () + hdr.GetSize () + fcs.GetSerializedSize ();
450  Ptr<Packet> p = AggregateToAmpdu (packet, hdr);
451  actualSize = p->GetSize ();
452  if (actualSize > size)
453  {
454  m_currentPacket = p;
455  return true;
456  }
457  return false;
458 }
459 
460 void
462  const WifiMacHeader* hdr,
464  Ptr<DcaTxop> dca)
465 {
466  if (m_phy->IsStateOff ())
467  {
468  NS_LOG_DEBUG ("Cannot start TX because device is OFF");
469  return;
470  }
471 
472  NS_LOG_FUNCTION (this << packet << hdr << params << dca);
473  /* m_currentPacket is not NULL because someone started
474  * a transmission and was interrupted before one of:
475  * - ctsTimeout
476  * - sendDataAfterCTS
477  * expired. This means that one of these timers is still
478  * running. They are all cancelled below anyway by the
479  * call to CancelAllEvents (because of at least one
480  * of these two timers) which will trigger a call to the
481  * previous listener's cancel method.
482  *
483  * This typically happens because the high-priority
484  * QapScheduler has taken access to the channel from
485  * one of the Edca of the QAP.
486  */
487  m_currentPacket = packet->Copy ();
488  // remove the priority tag attached, if any
489  SocketPriorityTag priorityTag;
490  m_currentPacket->RemovePacketTag (priorityTag);
491  m_currentHdr = *hdr;
492  CancelAllEvents ();
493  m_currentDca = dca;
494  m_txParams = params;
496 
497  if (NeedRts ())
498  {
500  }
501  else
502  {
504  }
505 
506  if (m_currentHdr.IsMgt ()
507  || (!m_currentHdr.IsQosData ()
508  && !m_currentHdr.IsBlockAck ()
509  && !m_currentHdr.IsBlockAckReq ()))
510  {
511  //This is mainly encountered when a higher priority control or management frame is
512  //sent between A-MPDU transmissions. It avoids to unexpectedly flush the aggregate
513  //queue when previous RTS request has failed.
514  m_ampdu = false;
515  }
516  else if (m_currentHdr.IsQosData () && !m_aggregateQueue[GetTid (packet, *hdr)]->IsEmpty ())
517  {
518  //m_aggregateQueue > 0 occurs when a RTS/CTS exchange failed before an A-MPDU transmission.
519  //In that case, we transmit the same A-MPDU as previously.
520  uint8_t sentMpdus = m_aggregateQueue[GetTid (packet, *hdr)]->GetNPackets ();
521  m_ampdu = true;
522  if (sentMpdus > 1)
523  {
525  }
526  else if (m_currentHdr.IsQosData ())
527  {
528  //VHT/HE single MPDUs are followed by normal ACKs
530  }
531  AcIndex ac = QosUtilsMapTidToAc (GetTid (packet, *hdr));
532  std::map<AcIndex, Ptr<EdcaTxopN> >::const_iterator edcaIt = m_edca.find (ac);
533  Ptr<Packet> aggregatedPacket = Create<Packet> ();
534  for (uint8_t i = 0; i < sentMpdus; i++)
535  {
536  Ptr<Packet> newPacket = (m_txPackets[GetTid (packet, *hdr)].at (i).packet)->Copy ();
537  newPacket->AddHeader (m_txPackets[GetTid (packet, *hdr)].at (i).hdr);
538  AddWifiMacTrailer (newPacket);
539  edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, aggregatedPacket);
540  }
541  m_currentPacket = aggregatedPacket;
542  m_currentHdr = (m_txPackets[GetTid (packet, *hdr)].at (0).hdr);
544  }
545  else
546  {
547  //Perform MPDU aggregation if possible
549  if (m_ampdu)
550  {
551  AmpduTag ampdu;
553  if (ampdu.GetRemainingNbOfMpdus () > 0)
554  {
556  }
557  else if (m_currentHdr.IsQosData ())
558  {
559  //VHT/HE single MPDUs are followed by normal ACKs
561  }
562  }
563  }
564 
565  NS_LOG_DEBUG ("startTx size=" << GetSize (m_currentPacket, &m_currentHdr, m_ampdu) <<
566  ", to=" << m_currentHdr.GetAddr1 () << ", dca=" << m_currentDca);
567 
568  if (m_txParams.MustSendRts ())
569  {
570  SendRtsForPacket ();
571  }
572  else
573  {
575  {
576  SendCtsToSelf ();
577  }
578  else
579  {
580  SendDataPacket ();
581  }
582  }
583 
584  /* When this method completes, either we have taken ownership of the medium or the device switched off in the meantime. */
586 }
587 
588 bool
589 MacLow::NeedRts (void) const
590 {
593  m_currentPacket, dataTxVector);
594 }
595 
596 bool
598 {
600  return m_stationManager->NeedCtsToSelf (dataTxVector);
601 }
602 
603 void
604 MacLow::ReceiveError (Ptr<Packet> packet, double rxSnr)
605 {
606  NS_LOG_FUNCTION (this << packet << rxSnr);
607  NS_LOG_DEBUG ("rx failed");
609  {
613  }
614  return;
615 }
616 
617 void
619 {
620  NS_LOG_DEBUG ("switching channel. Cancelling MAC pending events");
622  CancelAllEvents ();
624  {
626  }
629  m_currentPacket = 0;
630  m_currentDca = 0;
631 }
632 
633 void
635 {
636  NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
637  CancelAllEvents ();
639  {
641  }
644  m_currentPacket = 0;
645  m_currentDca = 0;
646 }
647 
648 void
650 {
651  NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events");
652  CancelAllEvents ();
654  {
656  }
659  m_currentPacket = 0;
660  m_currentDca = 0;
661 }
662 
663 void
664 MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, bool ampduSubframe)
665 {
666  NS_LOG_FUNCTION (this << packet << rxSnr << txVector.GetMode () << txVector.GetPreambleType ());
667  /* A packet is received from the PHY.
668  * When we have handled this packet,
669  * we handle any packet present in the
670  * packet queue.
671  */
672  WifiMacHeader hdr;
673  packet->RemoveHeader (hdr);
674  m_lastReceivedHdr = hdr;
675 
676  bool isPrevNavZero = IsNavZero ();
677  NS_LOG_DEBUG ("duration/id=" << hdr.GetDuration ());
678  NotifyNav (packet, hdr);
679  if (hdr.IsRts ())
680  {
681  /* see section 9.2.5.7 802.11-1999
682  * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS
683  * period if the NAV at the STA receiving the RTS frame indicates that the medium is
684  * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle,
685  * that STA shall not respond to the RTS frame.
686  */
687  if (ampduSubframe)
688  {
689  NS_FATAL_ERROR ("Received RTS as part of an A-MPDU");
690  }
691  else
692  {
693  if (isPrevNavZero
694  && hdr.GetAddr1 () == m_self)
695  {
696  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
698  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
699  rxSnr, txVector.GetMode ());
702  hdr.GetAddr2 (),
703  hdr.GetDuration (),
704  txVector,
705  rxSnr);
706  }
707  else
708  {
709  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
710  }
711  }
712  }
713  else if (hdr.IsCts ()
714  && hdr.GetAddr1 () == m_self
716  && m_currentPacket != 0)
717  {
718  if (ampduSubframe)
719  {
720  NS_FATAL_ERROR ("Received CTS as part of an A-MPDU");
721  }
722 
723  NS_LOG_DEBUG ("received cts from=" << m_currentHdr.GetAddr1 ());
724 
725  SnrTag tag;
726  packet->RemovePacketTag (tag);
728  rxSnr, txVector.GetMode ());
730  rxSnr, txVector.GetMode (), tag.Get ());
731 
737  hdr.GetDuration ());
738  }
739  else if (hdr.IsAck ()
740  && hdr.GetAddr1 () == m_self
744  && m_txParams.MustWaitAck ())
745  {
746  NS_LOG_DEBUG ("receive ack from=" << m_currentHdr.GetAddr1 ());
747  SnrTag tag;
748  packet->RemovePacketTag (tag);
749  //When fragmentation is used, only update manager when the last fragment is acknowledged
750  if (!m_txParams.HasNextPacket ())
751  {
753  rxSnr, txVector.GetMode ());
755  rxSnr, txVector.GetMode (), tag.Get ());
756  }
757  bool gotAck = false;
760  {
763  gotAck = true;
764  }
767  {
770  gotAck = true;
771  }
772  if (gotAck)
773  {
774  m_currentDca->GotAck ();
775  }
776  if (m_txParams.HasNextPacket () && (!m_currentHdr.IsQosData () || m_currentDca->GetTxopLimit ().IsZero () || m_currentDca->HasTxop ()))
777  {
779  {
781  }
782  else
783  {
785  }
786  }
787  else if (m_currentHdr.IsQosData () && m_currentDca->HasTxop ())
788  {
790  {
792  }
793  else
794  {
796  }
797  }
798  m_ampdu = false;
799  if (m_currentHdr.IsQosData ())
800  {
802  }
803  }
804  else if (hdr.IsBlockAck () && hdr.GetAddr1 () == m_self
807  {
808  NS_LOG_DEBUG ("got block ack from " << hdr.GetAddr2 ());
809  SnrTag tag;
810  packet->RemovePacketTag (tag);
811  FlushAggregateQueue (GetTid (packet, hdr));
812  CtrlBAckResponseHeader blockAck;
813  packet->RemoveHeader (blockAck);
816  m_currentDca->GotBlockAck (&blockAck, hdr.GetAddr2 (), rxSnr, txVector.GetMode (), tag.Get ());
817  m_ampdu = false;
818  if (m_currentHdr.IsQosData () && m_currentDca->HasTxop ())
819  {
821  {
823  }
824  else
825  {
827  }
828  }
829  }
830  else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
831  {
832  CtrlBAckRequestHeader blockAckReq;
833  packet->RemoveHeader (blockAckReq);
834  if (!blockAckReq.IsMultiTid ())
835  {
836  uint8_t tid = blockAckReq.GetTidInfo ();
837  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), tid));
838  if (it != m_bAckAgreements.end ())
839  {
840  //Update block ack cache
841  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), tid));
842  NS_ASSERT (i != m_bAckCaches.end ());
843  (*i).second.UpdateWithBlockAckReq (blockAckReq.GetStartingSequence ());
844 
845  //NS_ASSERT (m_sendAckEvent.IsExpired ());
847  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
848  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
849  if ((*it).second.first.IsImmediateBlockAck ())
850  {
851  NS_LOG_DEBUG ("rx blockAckRequest/sendImmediateBlockAck from=" << hdr.GetAddr2 ());
854  blockAckReq,
855  hdr.GetAddr2 (),
856  hdr.GetDuration (),
857  txVector.GetMode (),
858  rxSnr);
859  }
860  else
861  {
862  NS_FATAL_ERROR ("Delayed block ack not supported.");
863  }
864  }
865  else
866  {
867  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
868  }
869  }
870  else
871  {
872  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
873  }
874  }
875  else if (hdr.IsCtl ())
876  {
877  NS_LOG_DEBUG ("rx drop " << hdr.GetTypeString ());
878  }
879  else if (hdr.GetAddr1 () == m_self)
880  {
881  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
882  rxSnr, txVector.GetMode ());
883  if (hdr.IsQosData () && ReceiveMpdu (packet, hdr))
884  {
885  /* From section 9.10.4 in IEEE 802.11:
886  Upon the receipt of a QoS data frame from the originator for which
887  the Block Ack agreement exists, the recipient shall buffer the MSDU
888  regardless of the value of the Ack Policy subfield within the
889  QoS Control field of the QoS data frame. */
890  if (hdr.IsQosAck () && !ampduSubframe)
891  {
892  NS_LOG_DEBUG ("rx QoS unicast/sendAck from=" << hdr.GetAddr2 ());
893  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
894 
895  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (),
896  hdr.GetAddr2 (), hdr.GetQosTid ());
897  RxCompleteBufferedPacketsUntilFirstLost (hdr.GetAddr2 (), hdr.GetQosTid ());
901  hdr.GetAddr2 (),
902  hdr.GetDuration (),
903  txVector.GetMode (),
904  rxSnr);
905  }
906  else if (hdr.IsQosBlockAck ())
907  {
908  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
909  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
910  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
911  }
912  return;
913  }
914  else if (hdr.IsQosData () && hdr.IsQosBlockAck ())
915  {
916  /* This happens if a packet with ack policy Block Ack is received and a block ack
917  agreement for that packet doesn't exist.
918 
919  From section 11.5.3 in IEEE 802.11e:
920  When a recipient does not have an active Block ack for a TID, but receives
921  data MPDUs with the Ack Policy subfield set to Block Ack, it shall discard
922  them and shall send a DELBA frame using the normal access
923  mechanisms. */
924  AcIndex ac = QosUtilsMapTidToAc (hdr.GetQosTid ());
925  m_edca[ac]->SendDelbaFrame (hdr.GetAddr2 (), hdr.GetQosTid (), false);
926  return;
927  }
928  else if (hdr.IsQosData () && hdr.IsQosNoAck ())
929  {
930  if (ampduSubframe)
931  {
932  NS_LOG_DEBUG ("rx Ampdu with No Ack Policy from=" << hdr.GetAddr2 ());
933  }
934  else
935  {
936  NS_LOG_DEBUG ("rx unicast/noAck from=" << hdr.GetAddr2 ());
937  }
938  }
939  else if (hdr.IsData () || hdr.IsMgt ())
940  {
941  if (hdr.IsProbeResp ())
942  {
943  // Apply SNR tag for probe response quality measurements
944  SnrTag tag;
945  tag.Set (rxSnr);
946  packet->AddPacketTag (tag);
947  }
948  if (hdr.IsMgt () && ampduSubframe)
949  {
950  NS_FATAL_ERROR ("Received management packet as part of an A-MPDU");
951  }
952  else
953  {
954  NS_LOG_DEBUG ("rx unicast/sendAck from=" << hdr.GetAddr2 ());
958  hdr.GetAddr2 (),
959  hdr.GetDuration (),
960  txVector.GetMode (),
961  rxSnr);
962  }
963  }
964  goto rxPacket;
965  }
966  else if (hdr.GetAddr1 ().IsGroup ())
967  {
968  if (ampduSubframe)
969  {
970  NS_FATAL_ERROR ("Received group addressed packet as part of an A-MPDU");
971  }
972  else
973  {
974  if (hdr.IsData () || hdr.IsMgt ())
975  {
976  NS_LOG_DEBUG ("rx group from=" << hdr.GetAddr2 ());
977  if (hdr.IsBeacon ())
978  {
979  // Apply SNR tag for beacon quality measurements
980  SnrTag tag;
981  tag.Set (rxSnr);
982  packet->AddPacketTag (tag);
983  }
984  goto rxPacket;
985  }
986  }
987  }
988  else if (m_promisc)
989  {
990  NS_ASSERT (hdr.GetAddr1 () != m_self);
991  if (hdr.IsData ())
992  {
993  goto rxPacket;
994  }
995  }
996  else
997  {
998  NS_LOG_DEBUG ("rx not for me from=" << hdr.GetAddr2 ());
999  }
1000  return;
1001 rxPacket:
1002  WifiMacTrailer fcs;
1003  packet->RemoveTrailer (fcs);
1004  m_rxCallback (packet, &hdr);
1005  return;
1006 }
1007 
1008 Time
1010 {
1011  WifiTxVector ackTxVector = GetAckTxVectorForData (to, dataTxVector.GetMode ());
1012  return GetAckDuration (ackTxVector);
1013 }
1014 
1015 Time
1017 {
1018  NS_ASSERT (ackTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
1019  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetFrequency ());
1020 }
1021 
1022 Time
1023 MacLow::GetBlockAckDuration (WifiTxVector blockAckReqTxVector, BlockAckType type) const
1024 {
1025  /*
1026  * For immediate Basic BlockAck we should transmit the frame with the same WifiMode
1027  * as the BlockAckReq.
1028  */
1029  return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, m_phy->GetFrequency ());
1030 }
1031 
1032 Time
1034 {
1035  WifiTxVector ctsTxVector = GetCtsTxVectorForRts (to, rtsTxVector.GetMode ());
1036  return GetCtsDuration (ctsTxVector);
1037 }
1038 
1039 Time
1041 {
1042  NS_ASSERT (ctsTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1043  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetFrequency ());
1044 }
1045 
1048 {
1049  Mac48Address to = hdr->GetAddr1 ();
1050  return m_stationManager->GetRtsTxVector (to, hdr, packet);
1051 }
1052 
1055 {
1056  Mac48Address to = hdr->GetAddr1 ();
1057  return m_stationManager->GetDataTxVector (to, hdr, packet);
1058 }
1059 
1062 {
1063  return m_stationManager->GetCtsTxVector (to, rtsTxMode);
1064 }
1065 
1068 {
1069  return m_stationManager->GetAckTxVector (to, dataTxMode);
1070 }
1071 
1074 {
1075  return m_stationManager->GetBlockAckTxVector (to, dataTxMode);
1076 }
1077 
1080 {
1081  return GetCtsTxVector (to, rtsTxMode);
1082 }
1083 
1086 {
1087  return GetAckTxVector (to, dataTxMode);
1088 }
1089 
1090 Time
1092  const WifiMacHeader* hdr,
1093  const MacLowTransmissionParameters& params,
1094  uint32_t fragmentSize) const
1095 {
1096  Time txTime = Seconds (0);
1097  if (params.MustSendRts ())
1098  {
1099  WifiTxVector rtsTxVector = GetRtsTxVector (packet, hdr);
1100  txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetFrequency ());
1101  txTime += GetCtsDuration (hdr->GetAddr1 (), rtsTxVector);
1102  txTime += Time (GetSifs () * 2);
1103  }
1104  WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
1105  uint32_t dataSize;
1106  if (fragmentSize > 0)
1107  {
1108  Ptr<const Packet> fragment = Create<Packet> (fragmentSize);
1109  dataSize = GetSize (fragment, hdr, m_ampdu);
1110  }
1111  else
1112  {
1113  dataSize = GetSize (packet, hdr, m_ampdu);
1114  }
1115  txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, m_phy->GetFrequency ());
1116  txTime += GetSifs ();
1117  if (params.MustWaitAck ())
1118  {
1119  txTime += GetAckDuration (hdr->GetAddr1 (), dataTxVector);
1120  }
1121  return txTime;
1122 }
1123 
1124 Time
1126  const WifiMacHeader* hdr,
1127  const MacLowTransmissionParameters& params) const
1128 {
1129  Time txTime = CalculateOverallTxTime (packet, hdr, params);
1130  if (params.HasNextPacket ())
1131  {
1132  WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
1133  txTime += GetSifs ();
1134  txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, m_phy->GetFrequency ());
1135  }
1136  return txTime;
1137 }
1138 
1139 void
1141 {
1143  Time duration = hdr.GetDuration ();
1144 
1145  if (hdr.IsCfpoll ()
1146  && hdr.GetAddr2 () == m_bssid)
1147  {
1148  //see section 9.3.2.2 802.11-1999
1149  DoNavResetNow (duration);
1150  return;
1151  }
1154  else if (hdr.GetAddr1 () != m_self)
1155  {
1156  // see section 9.2.5.4 802.11-1999
1157  bool navUpdated = DoNavStartNow (duration);
1158  if (hdr.IsRts () && navUpdated)
1159  {
1168  WifiMacHeader cts;
1169  cts.SetType (WIFI_MAC_CTL_CTS);
1170  WifiTxVector txVector = GetRtsTxVector (packet, &hdr);
1171  Time navCounterResetCtsMissedDelay =
1172  m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, m_phy->GetFrequency ()) +
1173  Time (2 * GetSifs ()) + Time (2 * GetSlotTime ());
1174  m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
1176  Simulator::Now ());
1177  }
1178  }
1179 }
1180 
1181 void
1183 {
1184  if (m_phy->GetLastRxStartTime () < rtsEndRxTime)
1185  {
1186  DoNavResetNow (Seconds (0.0));
1187  }
1188 }
1189 
1190 void
1192 {
1193  for (DcfManagersCI i = m_dcfManagers.begin (); i != m_dcfManagers.end (); i++)
1194  {
1195  (*i)->NotifyNavResetNow (duration);
1196  }
1198  m_lastNavDuration = duration;
1199 }
1200 
1201 bool
1203 {
1204  for (DcfManagersCI i = m_dcfManagers.begin (); i != m_dcfManagers.end (); i++)
1205  {
1206  (*i)->NotifyNavStartNow (duration);
1207  }
1208  Time newNavEnd = Simulator::Now () + duration;
1209  Time oldNavEnd = m_lastNavStart + m_lastNavDuration;
1210  if (newNavEnd > oldNavEnd)
1211  {
1213  m_lastNavDuration = duration;
1214  return true;
1215  }
1216  return false;
1217 }
1218 
1219 void
1221 {
1222  for (DcfManagersCI i = m_dcfManagers.begin (); i != m_dcfManagers.end (); i++)
1223  {
1224  (*i)->NotifyAckTimeoutStartNow (duration);
1225  }
1226 }
1227 
1228 void
1230 {
1231  for (DcfManagersCI i = m_dcfManagers.begin (); i != m_dcfManagers.end (); i++)
1232  {
1233  (*i)->NotifyAckTimeoutResetNow ();
1234  }
1235 }
1236 
1237 void
1239 {
1240  for (DcfManagersCI i = m_dcfManagers.begin (); i != m_dcfManagers.end (); i++)
1241  {
1242  (*i)->NotifyCtsTimeoutStartNow (duration);
1243  }
1244 }
1245 
1246 void
1248 {
1249  for (DcfManagersCI i = m_dcfManagers.begin (); i != m_dcfManagers.end (); i++)
1250  {
1251  (*i)->NotifyCtsTimeoutResetNow ();
1252  }
1253 }
1254 
1255 void
1257 {
1258  NS_LOG_FUNCTION (this << packet << hdr << txVector);
1259  NS_LOG_DEBUG ("send " << hdr->GetTypeString () <<
1260  ", to=" << hdr->GetAddr1 () <<
1261  ", size=" << packet->GetSize () <<
1262  ", mode=" << txVector.GetMode () <<
1263  ", preamble=" << txVector.GetPreambleType () <<
1264  ", duration=" << hdr->GetDuration () <<
1265  ", seq=0x" << std::hex << m_currentHdr.GetSequenceControl () << std::dec);
1266  if (!m_ampdu || hdr->IsAck () || hdr->IsRts () || hdr->IsCts () || hdr->IsBlockAck () || hdr->IsMgt ())
1267  {
1268  m_phy->SendPacket (packet, txVector);
1269  }
1270  else
1271  {
1272  Ptr<Packet> newPacket;
1273  Ptr <WifiMacQueueItem> dequeuedItem;
1274  WifiMacHeader newHdr;
1275  uint8_t queueSize = m_aggregateQueue[GetTid (packet, *hdr)]->GetNPackets ();
1276  bool singleMpdu = false;
1277  bool last = false;
1278  MpduType mpdutype = NORMAL_MPDU;
1279 
1280  uint8_t tid = GetTid (packet, *hdr);
1281  AcIndex ac = QosUtilsMapTidToAc (tid);
1282  std::map<AcIndex, Ptr<EdcaTxopN> >::const_iterator edcaIt = m_edca.find (ac);
1283 
1284  if (queueSize == 1)
1285  {
1286  singleMpdu = true;
1287  }
1288 
1289  //Add packet tag
1290  AmpduTag ampdutag;
1291  Time delay = Seconds (0);
1292  Time remainingAmpduDuration = m_phy->CalculateTxDuration (packet->GetSize (), txVector, m_phy->GetFrequency ());
1293  if (queueSize > 1 || singleMpdu)
1294  {
1295  txVector.SetAggregation (true);
1296  }
1297  for (; queueSize > 0; queueSize--)
1298  {
1299  dequeuedItem = m_aggregateQueue[GetTid (packet, *hdr)]->Dequeue ();
1300  newHdr = dequeuedItem->GetHeader ();
1301  newPacket = dequeuedItem->GetPacket ()->Copy ();
1302  newHdr.SetDuration (hdr->GetDuration ());
1303  newPacket->AddHeader (newHdr);
1304  AddWifiMacTrailer (newPacket);
1305  if (queueSize == 1)
1306  {
1307  last = true;
1308  mpdutype = LAST_MPDU_IN_AGGREGATE;
1309  }
1310 
1311  edcaIt->second->GetMpduAggregator ()->AddHeaderAndPad (newPacket, last, singleMpdu);
1312 
1313  if (delay.IsZero ())
1314  {
1315  if (!singleMpdu)
1316  {
1317  NS_LOG_DEBUG ("Sending MPDU as part of A-MPDU");
1318  mpdutype = MPDU_IN_AGGREGATE;
1319  }
1320  else
1321  {
1322  NS_LOG_DEBUG ("Sending S-MPDU");
1323  mpdutype = NORMAL_MPDU;
1324  }
1325  }
1326 
1327  Time mpduDuration = m_phy->CalculateTxDuration (newPacket->GetSize (), txVector, m_phy->GetFrequency (), mpdutype, 0);
1328  remainingAmpduDuration -= mpduDuration;
1329 
1330  ampdutag.SetRemainingNbOfMpdus (queueSize - 1);
1331  if (queueSize > 1)
1332  {
1333  ampdutag.SetRemainingAmpduDuration (remainingAmpduDuration);
1334  }
1335  else
1336  {
1337  ampdutag.SetRemainingAmpduDuration (NanoSeconds (0));
1338  }
1339  newPacket->AddPacketTag (ampdutag);
1340 
1341  if (delay.IsZero ())
1342  {
1343  m_phy->SendPacket (newPacket, txVector, mpdutype);
1344  }
1345  else
1346  {
1347  Simulator::Schedule (delay, &MacLow::SendMpdu, this, newPacket, txVector, mpdutype);
1348  }
1349  if (queueSize > 1)
1350  {
1351  NS_ASSERT (remainingAmpduDuration > 0);
1352  delay = delay + mpduDuration;
1353  }
1354 
1356  }
1357  }
1358 }
1359 
1360 void
1362 {
1363  NS_LOG_DEBUG ("Sending MPDU as part of A-MPDU");
1364  m_phy->SendPacket (packet, txVector, mpdutype);
1365 }
1366 
1367 void
1369 {
1370  NS_LOG_FUNCTION (this);
1371  NS_LOG_DEBUG ("cts timeout");
1376  Ptr<DcaTxop> dca = m_currentDca;
1377  m_currentDca = 0;
1378  m_ampdu = false;
1379  dca->MissedCts ();
1380 }
1381 
1382 void
1384 {
1385  NS_LOG_FUNCTION (this);
1386  NS_LOG_DEBUG ("normal ack timeout");
1391  Ptr<DcaTxop> dca = m_currentDca;
1392  m_currentDca = 0;
1393  m_ampdu = false;
1394  if (m_currentHdr.IsQosData ())
1395  {
1397  }
1398  dca->MissedAck ();
1399 }
1400 
1401 void
1403 {
1404  NS_LOG_FUNCTION (this);
1406  Ptr<DcaTxop> dca = m_currentDca;
1407  m_currentDca = 0;
1408  if (m_phy->IsStateIdle ())
1409  {
1410  NS_LOG_DEBUG ("fast Ack idle missed");
1411  dca->MissedAck ();
1412  }
1413  else
1414  {
1415  NS_LOG_DEBUG ("fast Ack ok");
1416  }
1417 }
1418 
1419 void
1421 {
1422  NS_LOG_FUNCTION (this);
1423  NS_LOG_DEBUG ("block ack timeout");
1424  Ptr<DcaTxop> dca = m_currentDca;
1425  m_currentDca = 0;
1426  m_ampdu = false;
1427  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
1428  uint8_t nTxMpdus = m_aggregateQueue[tid]->GetNPackets ();
1429  FlushAggregateQueue (tid);
1430  dca->MissedBlockAck (nTxMpdus);
1431 }
1432 
1433 void
1435 {
1436  NS_LOG_FUNCTION (this);
1438  Ptr<DcaTxop> dca = m_currentDca;
1439  m_currentDca = 0;
1440  if (m_phy->IsStateIdle ())
1441  {
1442  NS_LOG_DEBUG ("super fast Ack failed");
1443  dca->MissedAck ();
1444  }
1445  else
1446  {
1447  NS_LOG_DEBUG ("super fast Ack ok");
1448  dca->GotAck ();
1449  }
1450 }
1451 
1452 void
1454 {
1455  NS_LOG_FUNCTION (this);
1456  /* send an RTS for this packet. */
1457  WifiMacHeader rts;
1458  rts.SetType (WIFI_MAC_CTL_RTS);
1459  rts.SetDsNotFrom ();
1460  rts.SetDsNotTo ();
1461  rts.SetNoRetry ();
1462  rts.SetNoMoreFragments ();
1463  rts.SetAddr1 (m_currentHdr.GetAddr1 ());
1464  rts.SetAddr2 (m_self);
1466  Time duration = Seconds (0);
1467 
1468  duration += GetSifs ();
1469  duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxVector);
1470  duration += GetSifs ();
1473  duration += GetSifs ();
1475  {
1477  duration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1478  }
1480  {
1482  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1483  }
1484  else if (m_txParams.MustWaitAck ())
1485  {
1487  }
1488  if (m_txParams.HasNextPacket ())
1489  {
1492  if (m_txParams.MustWaitAck ())
1493  {
1494  duration += GetSifs ();
1496  }
1497  }
1498  rts.SetDuration (duration);
1499 
1500  Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetFrequency ());
1501  Time timerDelay = txDuration + GetCtsTimeout ();
1502 
1504  NotifyCtsTimeoutStartNow (timerDelay);
1506 
1507  Ptr<Packet> packet = Create<Packet> ();
1508  packet->AddHeader (rts);
1509  AddWifiMacTrailer (packet);
1510 
1511  ForwardDown (packet, &rts, rtsTxVector);
1512 }
1513 
1514 void
1516 {
1519  {
1520  Time timerDelay = txDuration + GetAckTimeout ();
1522  NotifyAckTimeoutStartNow (timerDelay);
1524  }
1525  else if (m_txParams.MustWaitFastAck ())
1526  {
1527  Time timerDelay = txDuration + GetPifs ();
1529  NotifyAckTimeoutStartNow (timerDelay);
1531  }
1532  else if (m_txParams.MustWaitSuperFastAck ())
1533  {
1534  Time timerDelay = txDuration + GetPifs ();
1536  NotifyAckTimeoutStartNow (timerDelay);
1539  }
1540  else if (m_txParams.MustWaitBasicBlockAck ())
1541  {
1542  Time timerDelay = txDuration + GetBasicBlockAckTimeout ();
1544  NotifyAckTimeoutStartNow (timerDelay);
1546  }
1548  {
1549  Time timerDelay = txDuration + GetCompressedBlockAckTimeout ();
1551  NotifyAckTimeoutStartNow (timerDelay);
1553  }
1554  else if (m_txParams.HasNextPacket ())
1555  {
1557  Time delay = txDuration;
1559  {
1560  delay += GetRifs ();
1561  }
1562  else
1563  {
1564  delay += GetSifs ();
1565  }
1567  }
1568  else if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck () && m_currentDca->HasTxop ())
1569  {
1570  Time delay = txDuration;
1572  {
1573  delay += GetRifs ();
1574  }
1575  else
1576  {
1577  delay += GetSifs ();
1578  }
1580  }
1581  else
1582  {
1583  // since we do not expect any timer to be triggered.
1585  }
1586 }
1587 
1588 void
1590 {
1591  NS_LOG_FUNCTION (this);
1592  /* send this packet directly. No RTS is needed. */
1594 
1595  Time duration = Seconds (0.0);
1597  {
1598  duration += GetSifs ();
1600  duration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1601  }
1603  {
1604  duration += GetSifs ();
1606  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1607  }
1608  else if (m_txParams.MustWaitAck ())
1609  {
1610  duration += GetSifs ();
1612  }
1613  if (m_txParams.HasNextPacket ())
1614  {
1616  {
1617  duration += GetRifs ();
1618  }
1619  else
1620  {
1621  duration += GetSifs ();
1622  }
1625  if (m_txParams.MustWaitAck ())
1626  {
1627  duration += GetSifs ();
1629  }
1630  }
1631  m_currentHdr.SetDuration (duration);
1632  Ptr <Packet> packet = m_currentPacket->Copy ();
1633  if (m_ampdu)
1634  {
1636  }
1637  else
1638  {
1639  packet->AddHeader (m_currentHdr);
1640  AddWifiMacTrailer (packet);
1641  }
1643 }
1644 
1645 bool
1646 MacLow::IsNavZero (void) const
1647 {
1649 }
1650 
1651 void
1653 {
1654  WifiMacHeader cts;
1655  cts.SetType (WIFI_MAC_CTL_CTS);
1656  cts.SetDsNotFrom ();
1657  cts.SetDsNotTo ();
1658  cts.SetNoMoreFragments ();
1659  cts.SetNoRetry ();
1660  cts.SetAddr1 (m_self);
1661 
1663  Time duration = Seconds (0);
1664 
1665  duration += GetSifs ();
1669  {
1670  duration += GetSifs ();
1672  duration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1673  }
1675  {
1676  duration += GetSifs ();
1678  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1679  }
1680  else if (m_txParams.MustWaitAck ())
1681  {
1682  duration += GetSifs ();
1684  }
1685  if (m_txParams.HasNextPacket ())
1686  {
1687  duration += GetSifs ();
1691  {
1692  duration += GetSifs ();
1694  duration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1695  }
1696  else if (m_txParams.MustWaitAck ())
1697  {
1698  duration += GetSifs ();
1700  }
1701  }
1702 
1703  cts.SetDuration (duration);
1704 
1705  Ptr<Packet> packet = Create<Packet> ();
1706  packet->AddHeader (cts);
1707  AddWifiMacTrailer (packet);
1708 
1709  ForwardDown (packet, &cts, ctsTxVector);
1710 
1711  Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetFrequency ());
1712  txDuration += GetSifs ();
1714 
1715  m_sendDataEvent = Simulator::Schedule (txDuration,
1716  &MacLow::SendDataAfterCts, this,
1717  duration);
1718 }
1719 
1720 void
1721 MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
1722 {
1723  NS_LOG_FUNCTION (this << source << duration << rtsTxVector.GetMode () << rtsSnr);
1724  /* send a CTS when you receive a RTS
1725  * right after SIFS.
1726  */
1727  WifiTxVector ctsTxVector = GetCtsTxVector (source, rtsTxVector.GetMode ());
1728  WifiMacHeader cts;
1729  cts.SetType (WIFI_MAC_CTL_CTS);
1730  cts.SetDsNotFrom ();
1731  cts.SetDsNotTo ();
1732  cts.SetNoMoreFragments ();
1733  cts.SetNoRetry ();
1734  cts.SetAddr1 (source);
1735  duration -= GetCtsDuration (source, rtsTxVector);
1736  duration -= GetSifs ();
1737  NS_ASSERT (duration.IsPositive ());
1738  cts.SetDuration (duration);
1739 
1740  Ptr<Packet> packet = Create<Packet> ();
1741  packet->AddHeader (cts);
1742  AddWifiMacTrailer (packet);
1743 
1744  SnrTag tag;
1745  tag.Set (rtsSnr);
1746  packet->AddPacketTag (tag);
1747 
1748  //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1749  ForwardDown (packet, &cts, ctsTxVector);
1750 }
1751 
1752 void
1754 {
1755  NS_LOG_FUNCTION (this);
1756  /* send the third step in a
1757  * RTS/CTS/DATA/ACK hanshake
1758  */
1759  NS_ASSERT (m_currentPacket != 0);
1760 
1761  if (m_currentHdr.IsQosData ())
1762  {
1763  uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
1764  if (!m_aggregateQueue[GetTid (m_currentPacket, m_currentHdr)]->IsEmpty ())
1765  {
1766  for (std::vector<Item>::size_type i = 0; i != m_txPackets[tid].size (); i++)
1767  {
1768  AcIndex ac = QosUtilsMapTidToAc (tid);
1769  std::map<AcIndex, Ptr<EdcaTxopN> >::const_iterator edcaIt = m_edca.find (ac);
1770  edcaIt->second->CompleteMpduTx (m_txPackets[tid].at (i).packet, m_txPackets[tid].at (i).hdr, m_txPackets[tid].at (i).timestamp);
1771  }
1772  }
1773  }
1774 
1776  Time newDuration = Seconds (0);
1778  {
1779  newDuration += GetSifs ();
1781  newDuration += GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
1782  }
1784  {
1785  newDuration += GetSifs ();
1787  newDuration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1788  }
1789  else if (m_txParams.MustWaitAck ())
1790  {
1791  newDuration += GetSifs ();
1793  }
1794  if (m_txParams.HasNextPacket ())
1795  {
1797  {
1798  newDuration += GetRifs ();
1799  }
1800  else
1801  {
1802  newDuration += GetSifs ();
1803  }
1806  {
1807  newDuration += GetSifs ();
1809  newDuration += GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
1810  }
1811  else if (m_txParams.MustWaitAck ())
1812  {
1813  newDuration += GetSifs ();
1815  }
1816  }
1817 
1819  duration -= txDuration;
1820  duration -= GetSifs ();
1821 
1822  duration = std::max (duration, newDuration);
1823  NS_ASSERT (duration.IsPositive ());
1824  m_currentHdr.SetDuration (duration);
1825  Ptr <Packet> packet = m_currentPacket->Copy ();
1826  if (m_ampdu)
1827  {
1829  }
1830  else
1831  {
1832  packet->AddHeader (m_currentHdr);
1833  AddWifiMacTrailer (packet);
1834  }
1836 }
1837 
1838 void
1840 {
1841  NS_LOG_FUNCTION (this);
1842  m_currentDca->StartNextFragment ();
1843 }
1844 
1845 void
1847 {
1848  NS_LOG_FUNCTION (this);
1849  m_currentDca->StartNextPacket ();
1850 }
1851 
1852 void
1854 {
1855  NS_LOG_FUNCTION (this);
1856  Ptr<DcaTxop> dca = m_currentDca;
1857  m_currentDca = 0;
1858  dca->EndTxNoAck ();
1859 }
1860 
1861 void
1863 {
1864  NS_LOG_FUNCTION (this);
1865  Ptr<DcaTxop> dca = m_currentDca;
1866  m_currentDca = 0;
1867  dca->MissedAck ();
1868  NS_LOG_DEBUG ("fast Ack busy but missed");
1869 }
1870 
1871 void
1872 MacLow::SendAckAfterData (Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
1873 {
1874  NS_LOG_FUNCTION (this);
1875  // send an ACK, after SIFS, when you receive a packet
1876  WifiTxVector ackTxVector = GetAckTxVector (source, dataTxMode);
1877  WifiMacHeader ack;
1878  ack.SetType (WIFI_MAC_CTL_ACK);
1879  ack.SetDsNotFrom ();
1880  ack.SetDsNotTo ();
1881  ack.SetNoRetry ();
1882  ack.SetNoMoreFragments ();
1883  ack.SetAddr1 (source);
1884  // 802.11-2012, Section 8.3.1.4: Duration/ID is received duration value
1885  // minus the time to transmit the ACK frame and its SIFS interval
1886  duration -= GetAckDuration (ackTxVector);
1887  duration -= GetSifs ();
1888  NS_ASSERT_MSG (duration.IsPositive (), "Please provide test case to maintainers if this assert is hit.");
1889  ack.SetDuration (duration);
1890 
1891  Ptr<Packet> packet = Create<Packet> ();
1892  packet->AddHeader (ack);
1893  AddWifiMacTrailer (packet);
1894 
1895  SnrTag tag;
1896  tag.Set (dataSnr);
1897  packet->AddPacketTag (tag);
1898 
1899  //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
1900  ForwardDown (packet, &ack, ackTxVector);
1901 }
1902 
1903 bool
1905 {
1909  {
1910  Mac48Address originator = hdr.GetAddr2 ();
1911  uint8_t tid = 0;
1912  if (hdr.IsQosData ())
1913  {
1914  tid = hdr.GetQosTid ();
1915  }
1916  uint16_t seqNumber = hdr.GetSequenceNumber ();
1917  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
1918  if (it != m_bAckAgreements.end ())
1919  {
1920  //Implement HT immediate Block Ack support for HT Delayed Block Ack is not added yet
1921  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), seqNumber))
1922  {
1923  StoreMpduIfNeeded (packet, hdr);
1924  if (!IsInWindow (hdr.GetSequenceNumber (), (*it).second.first.GetStartingSequence (), (*it).second.first.GetBufferSize ()))
1925  {
1926  uint16_t delta = (seqNumber - (*it).second.first.GetWinEnd () + 4096) % 4096;
1927  if (delta > 1)
1928  {
1929  (*it).second.first.SetWinEnd (seqNumber);
1930  int16_t winEnd = (*it).second.first.GetWinEnd ();
1931  int16_t bufferSize = (*it).second.first.GetBufferSize ();
1932  uint16_t sum = (static_cast<uint16_t> (std::abs (winEnd - bufferSize + 1))) % 4096;
1933  (*it).second.first.SetStartingSequence (sum);
1934  RxCompleteBufferedPacketsWithSmallerSequence ((*it).second.first.GetStartingSequenceControl (), originator, tid);
1935  }
1936  }
1937  RxCompleteBufferedPacketsUntilFirstLost (originator, tid); //forwards up packets starting from winstart and set winstart to last +1
1938  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
1939  }
1940  return true;
1941  }
1942  return false;
1943  }
1944  return StoreMpduIfNeeded (packet, hdr);
1945 }
1946 
1947 bool
1949 {
1950  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1951  if (it != m_bAckAgreements.end ())
1952  {
1953  WifiMacTrailer fcs;
1954  packet->RemoveTrailer (fcs);
1955  BufferedPacket bufferedPacket (packet, hdr);
1956 
1957  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
1958  uint16_t mappedSeqControl = QosUtilsMapSeqControlToUniqueInteger (hdr.GetSequenceControl (), endSequence);
1959 
1960  BufferedPacketI i = (*it).second.second.begin ();
1961  for (; i != (*it).second.second.end ()
1962  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceControl (), endSequence) < mappedSeqControl; i++)
1963  {
1964  }
1965  (*it).second.second.insert (i, bufferedPacket);
1966 
1967  //Update block ack cache
1968  BlockAckCachesI j = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1969  NS_ASSERT (j != m_bAckCaches.end ());
1970  (*j).second.UpdateWithMpdu (&hdr);
1971  return true;
1972  }
1973  return false;
1974 }
1975 
1976 void
1978  uint16_t startingSeq)
1979 {
1980  NS_LOG_FUNCTION (this);
1981  uint8_t tid = respHdr->GetTid ();
1982  BlockAckAgreement agreement (originator, tid);
1983  if (respHdr->IsImmediateBlockAck ())
1984  {
1985  agreement.SetImmediateBlockAck ();
1986  }
1987  else
1988  {
1989  agreement.SetDelayedBlockAck ();
1990  }
1991  agreement.SetAmsduSupport (respHdr->IsAmsduSupported ());
1992  agreement.SetBufferSize (respHdr->GetBufferSize () + 1);
1993  agreement.SetTimeout (respHdr->GetTimeout ());
1994  agreement.SetStartingSequence (startingSeq);
1995 
1996  std::list<BufferedPacket> buffer (0);
1997  AgreementKey key (originator, respHdr->GetTid ());
1998  AgreementValue value (agreement, buffer);
1999  m_bAckAgreements.insert (std::make_pair (key, value));
2000 
2001  BlockAckCache cache;
2002  cache.Init (startingSeq, respHdr->GetBufferSize () + 1);
2003  m_bAckCaches.insert (std::make_pair (key, cache));
2004 
2005  if (respHdr->GetTimeout () != 0)
2006  {
2007  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, respHdr->GetTid ()));
2008  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2009 
2010  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2011 
2012  it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
2014  m_edca[ac], originator, tid, false);
2015  }
2016 }
2017 
2018 void
2020 {
2021  NS_LOG_FUNCTION (this);
2022  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2023  if (it != m_bAckAgreements.end ())
2024  {
2025  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (), originator, tid);
2026  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2027  m_bAckAgreements.erase (it);
2028  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2029  NS_ASSERT (i != m_bAckCaches.end ());
2030  m_bAckCaches.erase (i);
2031  }
2032 }
2033 
2034 void
2036 {
2037  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2038  if (it != m_bAckAgreements.end ())
2039  {
2040  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2041  uint16_t mappedStart = QosUtilsMapSeqControlToUniqueInteger (seq, endSequence);
2042  BufferedPacketI last = (*it).second.second.begin ();
2043  uint16_t guard = 0;
2044  if (last != (*it).second.second.end ())
2045  {
2046  guard = (*it).second.second.begin ()->second.GetSequenceControl ();
2047  }
2048  BufferedPacketI i = (*it).second.second.begin ();
2049  for (; i != (*it).second.second.end ()
2050  && QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceControl (), endSequence) < mappedStart; )
2051  {
2052  if (guard == (*i).second.GetSequenceControl ())
2053  {
2054  if (!(*i).second.IsMoreFragments ())
2055  {
2056  while (last != i)
2057  {
2058  m_rxCallback ((*last).first, &(*last).second);
2059  last++;
2060  }
2061  m_rxCallback ((*last).first, &(*last).second);
2062  last++;
2063  /* go to next packet */
2064  while (i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl ())
2065  {
2066  i++;
2067  }
2068  if (i != (*it).second.second.end ())
2069  {
2070  guard = (*i).second.GetSequenceControl ();
2071  last = i;
2072  }
2073  }
2074  else
2075  {
2076  guard++;
2077  }
2078  }
2079  else
2080  {
2081  /* go to next packet */
2082  while (i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl ())
2083  {
2084  i++;
2085  }
2086  if (i != (*it).second.second.end ())
2087  {
2088  guard = (*i).second.GetSequenceControl ();
2089  last = i;
2090  }
2091  }
2092  }
2093  (*it).second.second.erase ((*it).second.second.begin (), i);
2094  }
2095 }
2096 
2097 void
2099 {
2100  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2101  if (it != m_bAckAgreements.end ())
2102  {
2103  uint16_t guard = (*it).second.first.GetStartingSequenceControl ();
2104  BufferedPacketI lastComplete = (*it).second.second.begin ();
2105  BufferedPacketI i = (*it).second.second.begin ();
2106  for (; i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl (); i++)
2107  {
2108  if (!(*i).second.IsMoreFragments ())
2109  {
2110  while (lastComplete != i)
2111  {
2112  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2113  lastComplete++;
2114  }
2115  m_rxCallback ((*lastComplete).first, &(*lastComplete).second);
2116  lastComplete++;
2117  }
2118  guard = (*i).second.IsMoreFragments () ? (guard + 1) : ((guard + 16) & 0xfff0);
2119  }
2120  (*it).second.first.SetStartingSequenceControl (guard);
2121  /* All packets already forwarded to WifiMac must be removed from buffer:
2122  [begin (), lastComplete) */
2123  (*it).second.second.erase ((*it).second.second.begin (), lastComplete);
2124  }
2125 }
2126 void
2127 MacLow::SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate,
2128  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2129 {
2130  NS_LOG_FUNCTION (this);
2131  Ptr<Packet> packet = Create<Packet> ();
2132  packet->AddHeader (*blockAck);
2133 
2134  WifiMacHeader hdr;
2136  hdr.SetAddr1 (originator);
2137  hdr.SetAddr2 (GetAddress ());
2138  hdr.SetDsNotFrom ();
2139  hdr.SetDsNotTo ();
2140  hdr.SetNoRetry ();
2141  hdr.SetNoMoreFragments ();
2142 
2143  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (originator, blockAckReqTxMode);
2144 
2145  if (immediate)
2146  {
2148  duration -= GetSifs ();
2149  if (blockAck->IsBasic ())
2150  {
2151  duration -= GetBlockAckDuration (blockAckReqTxVector, BASIC_BLOCK_ACK);
2152  }
2153  else if (blockAck->IsCompressed ())
2154  {
2155  duration -= GetBlockAckDuration (blockAckReqTxVector, COMPRESSED_BLOCK_ACK);
2156  }
2157  else if (blockAck->IsMultiTid ())
2158  {
2159  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2160  }
2161  }
2162  else
2163  {
2164  m_txParams.EnableAck ();
2165  duration += GetSifs ();
2166  duration += GetAckDuration (originator, blockAckReqTxVector);
2167  }
2169 
2170  if (!immediate)
2171  {
2172  StartDataTxTimers (blockAckReqTxVector);
2173  }
2174 
2175  NS_ASSERT (duration.IsPositive ());
2176  hdr.SetDuration (duration);
2177  //here should be present a control about immediate or delayed block ack
2178  //for now we assume immediate
2179  packet->AddHeader (hdr);
2180  AddWifiMacTrailer (packet);
2181  SnrTag tag;
2182  tag.Set (rxSnr);
2183  packet->AddPacketTag (tag);
2184  ForwardDown (packet, &hdr, blockAckReqTxVector);
2185 }
2186 
2187 void
2188 MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector, double rxSnr)
2189 {
2190  NS_LOG_FUNCTION (this);
2191  if (!m_phy->IsStateTx () && !m_phy->IsStateRx ())
2192  {
2193  NS_LOG_FUNCTION (this << +tid << originator << duration.As (Time::S) << blockAckReqTxVector << rxSnr);
2194  CtrlBAckResponseHeader blockAck;
2195  uint16_t seqNumber = 0;
2196  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2197  NS_ASSERT (i != m_bAckCaches.end ());
2198  seqNumber = (*i).second.GetWinStart ();
2199 
2200  bool immediate = true;
2201  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2202  blockAck.SetStartingSequence (seqNumber);
2203  blockAck.SetTidInfo (tid);
2204  immediate = (*it).second.first.IsImmediateBlockAck ();
2205  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2206  NS_LOG_DEBUG ("Got Implicit block Ack Req with seq " << seqNumber);
2207  (*i).second.FillBlockAckBitmap (&blockAck);
2208 
2209  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxVector.GetMode (), rxSnr);
2210  }
2211  else
2212  {
2213  NS_LOG_DEBUG ("Skip block ack response!");
2214  }
2215 }
2216 
2217 void
2219  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2220 {
2221  NS_LOG_FUNCTION (this);
2222  CtrlBAckResponseHeader blockAck;
2223  uint8_t tid = 0;
2224  bool immediate = false;
2225  if (!reqHdr.IsMultiTid ())
2226  {
2227  tid = reqHdr.GetTidInfo ();
2228  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2229  if (it != m_bAckAgreements.end ())
2230  {
2231  blockAck.SetStartingSequence (reqHdr.GetStartingSequence ());
2232  blockAck.SetTidInfo (tid);
2233  immediate = (*it).second.first.IsImmediateBlockAck ();
2234  if (reqHdr.IsBasic ())
2235  {
2236  blockAck.SetType (BASIC_BLOCK_ACK);
2237  }
2238  else if (reqHdr.IsCompressed ())
2239  {
2240  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2241  }
2242  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2243  NS_ASSERT (i != m_bAckCaches.end ());
2244  (*i).second.FillBlockAckBitmap (&blockAck);
2245  NS_LOG_DEBUG ("Got block Ack Req with seq " << reqHdr.GetStartingSequence ());
2246 
2250  {
2251  /* All packets with smaller sequence than starting sequence control must be passed up to Wifimac
2252  * See 9.10.3 in IEEE 802.11e standard.
2253  */
2255  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2256  }
2257  else
2258  {
2259  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), reqHdr.GetStartingSequence ()))
2260  {
2261  (*it).second.first.SetStartingSequence (reqHdr.GetStartingSequence ());
2262  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2264  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2265  (*it).second.first.SetWinEnd (((*it).second.first.GetStartingSequence () + (*it).second.first.GetBufferSize () - 1) % 4096);
2266  }
2267  }
2268  }
2269  else
2270  {
2271  NS_LOG_DEBUG ("there's not a valid block ack agreement with " << originator);
2272  }
2273  }
2274  else
2275  {
2276  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2277  }
2278  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode, rxSnr);
2279 }
2280 
2281 void
2283 {
2284  if (agreement.GetTimeout () != 0)
2285  {
2286  NS_ASSERT (agreement.m_inactivityEvent.IsRunning ());
2287  agreement.m_inactivityEvent.Cancel ();
2288  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2289  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2290  agreement.m_inactivityEvent = Simulator::Schedule (timeout,
2292  m_edca[ac], agreement.GetPeer (),
2293  agreement.GetTid (), false);
2294  }
2295 }
2296 
2297 void
2299 {
2300  m_edca.insert (std::make_pair (ac, edca));
2301 }
2302 
2303 void
2304 MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiTxVector txVector)
2305 {
2306  NS_LOG_FUNCTION (this);
2307  AmpduTag ampdu;
2308  bool normalAck = false;
2309  bool ampduSubframe = false; //flag indicating the packet belongs to an A-MPDU and is not a VHT/HE single MPDU
2310  if (aggregatedPacket->RemovePacketTag (ampdu))
2311  {
2312  ampduSubframe = true;
2314  MpduAggregator::DeaggregatedMpdusCI n = packets.begin ();
2315 
2316  WifiMacHeader firsthdr;
2317  (*n).first->PeekHeader (firsthdr);
2318  NS_LOG_DEBUG ("duration/id=" << firsthdr.GetDuration ());
2319  NotifyNav ((*n).first, firsthdr);
2320 
2321  if (firsthdr.GetAddr1 () == m_self)
2322  {
2323  bool singleMpdu = (*n).second.GetEof ();
2324  if (singleMpdu)
2325  {
2326  //If the MPDU is sent as a VHT/HE single MPDU (EOF=1 in A-MPDU subframe header), then the responder sends an ACK.
2327  NS_LOG_DEBUG ("Receive S-MPDU");
2328  ampduSubframe = false;
2329  }
2330  else if (txVector.GetPreambleType () != WIFI_PREAMBLE_NONE || !m_sendAckEvent.IsRunning ())
2331  {
2334  firsthdr.GetQosTid (),
2335  firsthdr.GetAddr2 (),
2336  firsthdr.GetDuration (),
2337  txVector,
2338  rxSnr);
2339  }
2340 
2341  if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ())
2342  {
2343  ReceiveOk ((*n).first, rxSnr, txVector, ampduSubframe);
2344  }
2345  else if (firsthdr.IsData () || firsthdr.IsQosData ())
2346  {
2347  NS_LOG_DEBUG ("Deaggregate packet from " << firsthdr.GetAddr2 () << " with sequence=" << firsthdr.GetSequenceNumber ());
2348  ReceiveOk ((*n).first, rxSnr, txVector, ampduSubframe);
2349  if (firsthdr.IsQosAck ())
2350  {
2351  NS_LOG_DEBUG ("Normal Ack");
2352  normalAck = true;
2353  }
2354  }
2355  else
2356  {
2357  NS_FATAL_ERROR ("Received A-MPDU with invalid first MPDU type");
2358  }
2359 
2360  if (ampdu.GetRemainingNbOfMpdus () == 0 && !singleMpdu)
2361  {
2362  if (normalAck)
2363  {
2364  //send block Ack
2365  if (firsthdr.IsBlockAckReq ())
2366  {
2367  NS_FATAL_ERROR ("Sending a BlockAckReq with QosPolicy equal to Normal Ack");
2368  }
2369  uint8_t tid = firsthdr.GetQosTid ();
2370  AgreementsI it = m_bAckAgreements.find (std::make_pair (firsthdr.GetAddr2 (), tid));
2371  if (it != m_bAckAgreements.end ())
2372  {
2373  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
2374  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
2375  NS_LOG_DEBUG ("rx A-MPDU/sendImmediateBlockAck from=" << firsthdr.GetAddr2 ());
2377  }
2378  else
2379  {
2380  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
2381  }
2382  }
2383  }
2384  }
2385  }
2386  else
2387  {
2388  ReceiveOk (aggregatedPacket, rxSnr, txVector, ampduSubframe);
2389  }
2390 }
2391 
2392 bool
2393 MacLow::StopMpduAggregation (Ptr<const Packet> peekedPacket, WifiMacHeader peekedHdr, Ptr<Packet> aggregatedPacket, uint16_t size) const
2394 {
2395  if (peekedPacket == 0)
2396  {
2397  NS_LOG_DEBUG ("no more packets in queue");
2398  return true;
2399  }
2400 
2401  Time aPPDUMaxTime = MicroSeconds (5484);
2402  uint8_t tid = GetTid (peekedPacket, peekedHdr);
2403  AcIndex ac = QosUtilsMapTidToAc (tid);
2404  std::map<AcIndex, Ptr<EdcaTxopN> >::const_iterator edcaIt = m_edca.find (ac);
2405 
2406  if (m_phy->GetGreenfield ())
2407  {
2408  aPPDUMaxTime = MicroSeconds (10000);
2409  }
2410 
2411  //A STA shall not transmit a PPDU that has a duration that is greater than aPPDUMaxTime
2412  if (m_phy->CalculateTxDuration (aggregatedPacket->GetSize () + peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, m_currentTxVector, m_phy->GetFrequency ()) > aPPDUMaxTime)
2413  {
2414  NS_LOG_DEBUG ("no more packets can be aggregated to satisfy PPDU <= aPPDUMaxTime");
2415  return true;
2416  }
2417 
2418  if (!edcaIt->second->GetMpduAggregator ()->CanBeAggregated (peekedPacket->GetSize () + peekedHdr.GetSize () + WIFI_MAC_FCS_LENGTH, aggregatedPacket, size))
2419  {
2420  NS_LOG_DEBUG ("no more packets can be aggregated because the maximum A-MPDU size has been reached");
2421  return true;
2422  }
2423 
2424  return false;
2425 }
2426 
2429 {
2430  bool isAmpdu = false;
2431  Ptr<Packet> newPacket, tempPacket;
2432  WifiMacHeader peekedHdr;
2433  newPacket = packet->Copy ();
2434  Ptr<Packet> currentAggregatedPacket;
2435  CtrlBAckRequestHeader blockAckReq;
2436 
2437  if (hdr.IsBlockAckReq ())
2438  {
2439  //Workaround to avoid BlockAckReq to be part of an A-MPDU. The standard says that
2440  //BlockAckReq is not present in A-MPDU if any QoS data frames for that TID are present.
2441  //Since an A-MPDU in non-PSMP frame exchanges aggregates MPDUs from one TID, this means
2442  //we should stop aggregation here for single-TID A-MPDUs. Once PSMP and multi-TID A-MPDUs
2443  //are supported, the condition of entering here should be changed.
2444  return newPacket;
2445  }
2446 
2447  //missing hdr.IsAck() since we have no means of knowing the Tid of the Ack yet
2448  if (hdr.IsQosData () || hdr.IsBlockAck ()|| hdr.IsBlockAckReq ())
2449  {
2450  Time tstamp;
2451  uint8_t tid = GetTid (packet, hdr);
2452  Ptr<WifiMacQueue> queue;
2453  AcIndex ac = QosUtilsMapTidToAc (tid);
2454  std::map<AcIndex, Ptr<EdcaTxopN> >::const_iterator edcaIt = m_edca.find (ac);
2455  NS_ASSERT (edcaIt != m_edca.end ());
2456  queue = edcaIt->second->GetQueue ();
2457 
2458  if (!hdr.GetAddr1 ().IsBroadcast () && edcaIt->second->GetMpduAggregator () != 0)
2459  {
2460  //Have to make sure that their exist a block Ack agreement before sending an AMPDU (BlockAck Manager)
2461  if (edcaIt->second->GetBaAgreementExists (hdr.GetAddr1 (), tid))
2462  {
2463  /* here is performed mpdu aggregation */
2464  /* MSDU aggregation happened in edca if the user asked for it so m_currentPacket may contains a normal packet or a A-MSDU*/
2465  currentAggregatedPacket = Create<Packet> ();
2466  peekedHdr = hdr;
2467  uint16_t startingSequenceNumber = 0;
2468  uint16_t currentSequenceNumber = 0;
2469  uint8_t qosPolicy = 0;
2470  uint16_t blockAckSize = 0;
2471  bool aggregated = false;
2472  int i = 0;
2473  Ptr<Packet> aggPacket = newPacket->Copy ();
2474 
2475  if (!hdr.IsBlockAckReq ())
2476  {
2477  if (!hdr.IsBlockAck ())
2478  {
2479  startingSequenceNumber = peekedHdr.GetSequenceNumber ();
2480  peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
2481  }
2482  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
2483  newPacket->AddHeader (peekedHdr);
2484  AddWifiMacTrailer (newPacket);
2485 
2486  aggregated = edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
2487 
2488  if (aggregated)
2489  {
2490  NS_LOG_DEBUG ("Adding packet with sequence number " << currentSequenceNumber << " to A-MPDU, packet size = " << newPacket->GetSize () << ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
2491  i++;
2492  m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (aggPacket, peekedHdr));
2493  }
2494  }
2495  else if (hdr.IsBlockAckReq ())
2496  {
2497  blockAckSize = packet->GetSize () + hdr.GetSize () + WIFI_MAC_FCS_LENGTH;
2498  qosPolicy = 3; //if the last subrame is block ack req then set ack policy of all frames to blockack
2499  packet->PeekHeader (blockAckReq);
2500  startingSequenceNumber = blockAckReq.GetStartingSequence ();
2501  }
2503  bool retry = false;
2504  //looks for other packets to the same destination with the same Tid need to extend that to include MSDUs
2505  Ptr<const Packet> peekedPacket = edcaIt->second->PeekNextRetransmitPacket (peekedHdr, peekedHdr.GetAddr1 (), tid, &tstamp);
2506  if (peekedPacket == 0)
2507  {
2508  Ptr<const WifiMacQueueItem> item = queue->PeekByTidAndAddress (tid,
2510  hdr.GetAddr1 ());
2511  if (item)
2512  {
2513  peekedPacket = item->GetPacket ();
2514  peekedHdr = item->GetHeader ();
2515  tstamp = item->GetTimeStamp ();
2516  }
2517  currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&peekedHdr);
2518 
2519  /* here is performed MSDU aggregation (two-level aggregation) */
2520  if (peekedPacket != 0 && edcaIt->second->GetMsduAggregator () != 0)
2521  {
2522  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
2523  if (tempPacket != 0) //MSDU aggregation
2524  {
2525  peekedPacket = tempPacket->Copy ();
2526  }
2527  }
2528  }
2529  else
2530  {
2531  retry = true;
2532  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
2533  }
2534 
2535  while (IsInWindow (currentSequenceNumber, startingSequenceNumber, 64) && !StopMpduAggregation (peekedPacket, peekedHdr, currentAggregatedPacket, blockAckSize))
2536  {
2537  //for now always send AMPDU with normal ACK
2538  if (retry == false)
2539  {
2540  currentSequenceNumber = edcaIt->second->GetNextSequenceNumberFor (&peekedHdr);
2541  peekedHdr.SetSequenceNumber (currentSequenceNumber);
2542  peekedHdr.SetFragmentNumber (0);
2543  peekedHdr.SetNoMoreFragments ();
2544  peekedHdr.SetNoRetry ();
2545  }
2546  if (qosPolicy == 0)
2547  {
2548  peekedHdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
2549  }
2550  else
2551  {
2552  peekedHdr.SetQosAckPolicy (WifiMacHeader::BLOCK_ACK);
2553  }
2554 
2555  newPacket = peekedPacket->Copy ();
2556  Ptr<Packet> aggPacket = newPacket->Copy ();
2557 
2558  newPacket->AddHeader (peekedHdr);
2559  AddWifiMacTrailer (newPacket);
2560  aggregated = edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
2561  if (aggregated)
2562  {
2563  m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (aggPacket, peekedHdr));
2564  if (i == 1 && hdr.IsQosData ())
2565  {
2566  if (!m_txParams.MustSendRts ())
2567  {
2568  edcaIt->second->CompleteMpduTx (packet, hdr, tstamp);
2569  }
2570  else
2571  {
2572  InsertInTxQueue (packet, hdr, tstamp, tid);
2573  }
2574  }
2575  NS_LOG_DEBUG ("Adding packet with sequence number " << peekedHdr.GetSequenceNumber () << " to A-MPDU, packet size = " << newPacket->GetSize () << ", A-MPDU size = " << currentAggregatedPacket->GetSize ());
2576  i++;
2577  isAmpdu = true;
2578  if (!m_txParams.MustSendRts ())
2579  {
2580  edcaIt->second->CompleteMpduTx (peekedPacket, peekedHdr, tstamp);
2581  }
2582  else
2583  {
2584  InsertInTxQueue (peekedPacket, peekedHdr, tstamp, tid);
2585  }
2586  if (retry)
2587  {
2588  edcaIt->second->RemoveRetransmitPacket (tid, hdr.GetAddr1 (), peekedHdr.GetSequenceNumber ());
2589  }
2590  else
2591  {
2592  queue->Remove (peekedPacket);
2593  }
2594  newPacket = 0;
2595  }
2596  else
2597  {
2598  break;
2599  }
2600  if (retry == true)
2601  {
2602  peekedPacket = edcaIt->second->PeekNextRetransmitPacket (peekedHdr, hdr.GetAddr1 (), tid, &tstamp);
2603  if (peekedPacket == 0)
2604  {
2605  //I reached the first packet that I added to this A-MPDU
2606  retry = false;
2607  Ptr<const WifiMacQueueItem> item = queue->PeekByTidAndAddress (tid,
2609  hdr.GetAddr1 ());
2610  if (item != 0)
2611  {
2612  peekedPacket = item->GetPacket ();
2613  peekedHdr = item->GetHeader ();
2614  tstamp = item->GetTimeStamp ();
2615  //find what will the sequence number be so that we don't send more than 64 packets apart
2616  currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&peekedHdr);
2617 
2618  if (edcaIt->second->GetMsduAggregator () != 0)
2619  {
2620  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
2621  if (tempPacket != 0) //MSDU aggregation
2622  {
2623  peekedPacket = tempPacket->Copy ();
2624  }
2625  }
2626  }
2627  }
2628  else
2629  {
2630  currentSequenceNumber = peekedHdr.GetSequenceNumber ();
2631  }
2632  }
2633  else
2634  {
2635  Ptr<const WifiMacQueueItem> item = queue->PeekByTidAndAddress (tid,
2636  WifiMacHeader::ADDR1, hdr.GetAddr1 ());
2637  if (item != 0)
2638  {
2639  peekedPacket = item->GetPacket ();
2640  peekedHdr = item->GetHeader ();
2641  tstamp = item->GetTimeStamp ();
2642  //find what will the sequence number be so that we don't send more than 64 packets apart
2643  currentSequenceNumber = edcaIt->second->PeekNextSequenceNumberFor (&peekedHdr);
2644 
2645  if (edcaIt->second->GetMsduAggregator () != 0 && IsInWindow (currentSequenceNumber, startingSequenceNumber, 64))
2646  {
2647  tempPacket = PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, blockAckSize);
2648  if (tempPacket != 0) //MSDU aggregation
2649  {
2650  peekedPacket = tempPacket->Copy ();
2651  }
2652  }
2653  }
2654  else
2655  {
2656  peekedPacket = 0;
2657  }
2658  }
2659  }
2660 
2661  if (isAmpdu)
2662  {
2663  if (hdr.IsBlockAckReq ())
2664  {
2665  newPacket = packet->Copy ();
2666  peekedHdr = hdr;
2667  Ptr<Packet> aggPacket = newPacket->Copy ();
2668  m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (aggPacket, peekedHdr));
2669  newPacket->AddHeader (peekedHdr);
2670  AddWifiMacTrailer (newPacket);
2671  edcaIt->second->GetMpduAggregator ()->Aggregate (newPacket, currentAggregatedPacket);
2672  currentAggregatedPacket->AddHeader (blockAckReq);
2673  }
2674 
2675  if (qosPolicy == 0)
2676  {
2677  edcaIt->second->CompleteAmpduTransfer (hdr.GetAddr1 (), tid);
2678  }
2679 
2680  //Add packet tag
2681  AmpduTag ampdutag;
2682  ampdutag.SetRemainingNbOfMpdus (i - 1);
2683  newPacket = currentAggregatedPacket;
2684  newPacket->AddPacketTag (ampdutag);
2685 
2686  NS_LOG_DEBUG ("tx unicast A-MPDU");
2687  edcaIt->second->SetAmpduExist (hdr.GetAddr1 (), true);
2688  }
2689  else
2690  {
2691  uint8_t queueSize = m_aggregateQueue[tid]->GetNPackets ();
2692  NS_ASSERT (queueSize <= 2); //since it is not an A-MPDU then only 2 packets should have been added to the queue no more
2693  if (queueSize >= 1)
2694  {
2695  //remove any packets that we added to the aggregate queue
2696  FlushAggregateQueue (tid);
2697  }
2698  }
2699  }
2700  // VHT/HE single MPDU operation
2702  if (!isAmpdu
2703  && hdr.IsQosData ()
2704  && (dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_VHT
2705  || dataTxVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HE))
2706  {
2707  peekedHdr = hdr;
2709 
2710  currentAggregatedPacket = Create<Packet> ();
2711  edcaIt->second->GetMpduAggregator ()->AggregateSingleMpdu (packet, currentAggregatedPacket);
2712  m_aggregateQueue[tid]->Enqueue (Create<WifiMacQueueItem> (packet, peekedHdr));
2713  if (m_txParams.MustSendRts ())
2714  {
2715  InsertInTxQueue (packet, peekedHdr, tstamp, tid);
2716  }
2717  if (edcaIt->second->GetBaAgreementExists (hdr.GetAddr1 (), tid))
2718  {
2719  edcaIt->second->CompleteAmpduTransfer (peekedHdr.GetAddr1 (), tid);
2720  }
2721 
2722  //Add packet tag
2723  AmpduTag ampdutag;
2724  newPacket = currentAggregatedPacket;
2725  newPacket->AddHeader (peekedHdr);
2726  AddWifiMacTrailer (newPacket);
2727  newPacket->AddPacketTag (ampdutag);
2728 
2729  NS_LOG_DEBUG ("tx unicast S-MPDU with sequence number " << hdr.GetSequenceNumber ());
2730  edcaIt->second->SetAmpduExist (hdr.GetAddr1 (), true);
2731  }
2732  }
2733  }
2734  return newPacket;
2735 }
2736 
2737 void
2739 {
2740  if (!m_aggregateQueue[tid]->IsEmpty ())
2741  {
2742  NS_LOG_DEBUG ("Flush aggregate queue");
2743  m_aggregateQueue[tid]->Flush ();
2744  }
2745  m_txPackets[tid].clear ();
2746 }
2747 
2748 void
2749 MacLow::InsertInTxQueue (Ptr<const Packet> packet, const WifiMacHeader &hdr, Time tStamp, uint8_t tid)
2750 {
2751  NS_LOG_FUNCTION (this);
2752  Item item;
2753  item.packet = packet;
2754  item.hdr = hdr;
2755  item.timestamp = tStamp;
2756  m_txPackets[tid].push_back (item);
2757 }
2758 
2760 MacLow::PerformMsduAggregation (Ptr<const Packet> packet, WifiMacHeader *hdr, Time *tstamp, Ptr<Packet> currentAmpduPacket, uint16_t blockAckSize)
2761 {
2762  bool msduAggregation = false;
2763  bool isAmsdu = false;
2764  Ptr<Packet> currentAmsduPacket = Create<Packet> ();
2765  Ptr<Packet> tempPacket = Create<Packet> ();
2766 
2767  Ptr<WifiMacQueue> queue;
2768  AcIndex ac = QosUtilsMapTidToAc (GetTid (packet, *hdr));
2769  std::map<AcIndex, Ptr<EdcaTxopN> >::const_iterator edcaIt = m_edca.find (ac);
2770  NS_ASSERT (edcaIt != m_edca.end ());
2771  queue = edcaIt->second->GetQueue ();
2772 
2773  Ptr<const WifiMacQueueItem> peekedItem = queue->DequeueByTidAndAddress (hdr->GetQosTid (),
2775  hdr->GetAddr1 ());
2776  if (peekedItem)
2777  {
2778  *hdr = peekedItem->GetHeader ();
2779  }
2780 
2781  edcaIt->second->GetMsduAggregator ()->Aggregate (packet, currentAmsduPacket,
2782  edcaIt->second->MapSrcAddressForAggregation (*hdr),
2783  edcaIt->second->MapDestAddressForAggregation (*hdr));
2784 
2785  peekedItem = queue->PeekByTidAndAddress (hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 ());
2786  while (peekedItem != 0)
2787  {
2788  *hdr = peekedItem->GetHeader ();
2789  *tstamp = peekedItem->GetTimeStamp ();
2790  tempPacket = currentAmsduPacket;
2791 
2792  msduAggregation = edcaIt->second->GetMsduAggregator ()->Aggregate (peekedItem->GetPacket (), tempPacket,
2793  edcaIt->second->MapSrcAddressForAggregation (*hdr),
2794  edcaIt->second->MapDestAddressForAggregation (*hdr));
2795 
2796  if (msduAggregation && !StopMpduAggregation (tempPacket, *hdr, currentAmpduPacket, blockAckSize))
2797  {
2798  isAmsdu = true;
2799  currentAmsduPacket = tempPacket;
2800  queue->Remove (peekedItem->GetPacket ());
2801  }
2802  else
2803  {
2804  break;
2805  }
2806  peekedItem = queue->PeekByTidAndAddress (hdr->GetQosTid (), WifiMacHeader::ADDR1, hdr->GetAddr1 ());
2807  }
2808 
2809  if (isAmsdu)
2810  {
2811  NS_LOG_DEBUG ("A-MSDU with size = " << currentAmsduPacket->GetSize ());
2812  hdr->SetQosAmsdu ();
2813  hdr->SetAddr3 (GetBssid ());
2814  return currentAmsduPacket;
2815  }
2816  else
2817  {
2818  queue->PushFront (Create<WifiMacQueueItem> (packet, *hdr));
2819  return 0;
2820  }
2821 }
2822 
2823 } //namespace ns3
void WaitIfsAfterEndTxPacket(void)
Event handler that is usually scheduled to fired at the appropriate time after sending a packet...
Definition: mac-low.cc:1846
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void Set(double snr)
Set the SNR to the given value.
Definition: snr-tag.cc:83
Time GetPifs(void) const
Return PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:415
void SetPifs(Time pifs)
Set PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:341
Time m_ctsTimeout
CTS timeout duration.
Definition: mac-low.h:876
uint16_t GetBufferSize(void) const
Return the buffer size.
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:864
The MPDU is not part of an A-MPDU.
Definition: wifi-phy.h:64
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
bool IsPositive(void) const
Definition: nstime.h:298
#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:266
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:2282
EventId m_blockAckTimeoutEvent
Block ACK timeout event.
Definition: mac-low.h:857
Callback template class.
Definition: callback.h:1176
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
std::vector< Item > m_txPackets[8]
Contain temporary items to be sent with the next A-MPDU transmission for a given TID, once RTS/CTS exchange has succeeded.
Definition: mac-low.h:913
uint8_t GetRemainingNbOfMpdus(void) const
Definition: ampdu-tag.cc:90
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:1016
void SetType(WifiMacType type)
Set Type/Subtype values with the correct values depending on the given type.
void SendBlockAckAfterBlockAckRequest(const CtrlBAckRequestHeader reqHdr, Mac48Address originator, Time duration, WifiMode blockAckReqTxMode, double rxSnr)
Invoked after that a block ack request has been received.
Definition: mac-low.cc:2218
virtual void StartTransmission(Ptr< const Packet > packet, const WifiMacHeader *hdr, MacLowTransmissionParameters parameters, Ptr< DcaTxop > dca)
Definition: mac-low.cc:461
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:359
bool GetGreenfield(void) const
Return whether Greenfield is supported.
Definition: wifi-phy.cc:608
void AddWifiMacTrailer(Ptr< Packet > packet)
Add FCS trailer to a packet.
Definition: wifi-utils.cc:152
void DoNavResetNow(Time duration)
Reset NAV with the given duration.
Definition: mac-low.cc:1191
void ReportDataFailed(Mac48Address address, const WifiMacHeader *header)
Should be invoked whenever the AckTimeout associated to a transmission attempt expires.
void NotifyMaybeCcaBusyStart(Time duration)
Definition: mac-low.cc:70
bool IsPromisc(void) const
Check if MacLow is operating in promiscuous mode.
Definition: mac-low.cc:427
bool GetUseNonErpProtection(void) const
Return whether the device supports protection of non-ERP stations.
void SetupPhyMacLowListener(const Ptr< WifiPhy > phy)
Set up WifiPhy listener for this MacLow.
Definition: mac-low.cc:143
uint32_t GetRtsSize(void)
Return the total RTS size (including FCS trailer).
Definition: wifi-utils.cc:130
Mac48Address GetPeer(void) const
Return the peer address.
bool IsStateRx(void) const
Definition: wifi-phy.cc:3606
EventId m_fastAckTimeoutEvent
Fast ACK timeout event.
Definition: mac-low.h:854
bool IsZero(void) const
Definition: nstime.h:288
Time m_pifs
PCF Interframe Space (PIFS) duration.
Definition: mac-low.h:879
void SetPhy(const Ptr< WifiPhy > phy)
Set up WifiPhy associated with this MacLow.
Definition: mac-low.cc:257
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:852
uint32_t GetSize(Ptr< const Packet > packet, const WifiMacHeader *hdr, bool isAmpdu)
Return the total size of the packet after WifiMacHeader and FCS trailer have been added...
Definition: wifi-utils.cc:159
bool DoNavStartNow(Time duration)
Start NAV with the given duration.
Definition: mac-low.cc:1202
void FastAckFailedTimeout(void)
Event handler when fast ACK timeout occurs (busy).
Definition: mac-low.cc:1862
Mac48Address GetBssid(void) const
Return the Basic Service Set Identification.
Definition: mac-low.cc:421
void SetSifs(Time sifs)
Set Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:329
void NotifySwitchingStart(Time duration)
Definition: mac-low.cc:73
void ForwardDown(Ptr< const Packet > packet, const WifiMacHeader *hdr, WifiTxVector txVector)
Forward the packet down to WifiPhy for transmission.
Definition: mac-low.cc:1256
Ptr< DcaTxop > m_currentDca
Current DCA.
Definition: mac-low.h:868
std::pair< Mac48Address, uint8_t > AgreementKey
agreement key typedef
Definition: mac-low.h:896
void SetNoMoreFragments(void)
Un-set the More Fragment bit in the Frame Control Field.
bool IsImmediateBlockAck(void) const
Return whether the Block ACK policy is immediate Block ACK.
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:412
WifiTxVector GetCtsTxVector(Mac48Address address, WifiMode rtsMode)
Time CalculateOverallTxTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &params, uint32_t fragmentSize=0) const
Definition: mac-low.cc:1091
#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)
Init function.
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.
The MPDU is the last aggregate in an A-MPDU.
Definition: wifi-phy.h:68
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:821
static DeaggregatedMpdus Deaggregate(Ptr< Packet > aggregatedPacket)
Deaggregates an A-MPDU by removing the A-MPDU subframe header and padding.
bool IsBroadcast(void) const
void NotifyOffNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:649
second
Definition: nstime.h:114
void NotifySleepNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:634
void NotifyNav(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Notify NAV function.
Definition: mac-low.cc:1140
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
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.
void UnregisterListener(WifiPhyListener *listener)
Definition: wifi-phy.cc:424
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
bool QosUtilsIsOldPacket(uint16_t startingSeq, uint16_t seqNumber)
This function checks if packet with sequence number seqNumber is an "old" packet. ...
Definition: qos-utils.cc:80
void SendPacket(Ptr< const Packet > packet, WifiTxVector txVector, MpduType mpdutype=NORMAL_MPDU)
Definition: wifi-phy.cc:2355
uint32_t GetAckSize(void)
Return the total ACK size (including FCS trailer).
Definition: wifi-utils.cc:100
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:733
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:886
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
bool NeedRts(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet, WifiTxVector txVector)
void SetRxCallback(Callback< void, Ptr< Packet >, const WifiMacHeader * > callback)
Definition: mac-low.cc:433
Time GetCompressedBlockAckTimeout() const
Return Compressed Block ACK timeout of this MacLow.
Definition: mac-low.cc:383
Callback< R > MakeNullCallback(void)
Definition: callback.h:1635
VHT PHY (Clause 22)
Definition: wifi-mode.h:60
Mac48Address m_bssid
BSSID address (Mac48Address)
Definition: mac-low.h:872
ns3::Time timeout
BlockAckType
Enumeration for different block ACK policies.
Definition: ctrl-headers.h:31
Ptr< Packet > AggregateToAmpdu(Ptr< const Packet > packet, const WifiMacHeader hdr)
Definition: mac-low.cc:2428
EventId m_sendCtsEvent
Event to send CTS.
Definition: mac-low.h:859
MacLowRxCallback m_rxCallback
Callback to pass packet up.
Definition: mac-low.h:831
Time GetCtsTimeout(void) const
Return CTS timeout of this MacLow.
Definition: mac-low.cc:389
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:855
void DeaggregateAmpduAndReceive(Ptr< Packet > aggregatedPacket, double rxSnr, WifiTxVector txVector)
Definition: mac-low.cc:2304
EventId m_sendAckEvent
Event to send ACK.
Definition: mac-low.h:860
uint16_t GetFrequency(void) const
Definition: wifi-phy.cc:1260
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
Time GetCtsDuration(WifiTxVector ctsTxVector) const
Return the time required to transmit the CTS (including preamble and FCS).
Definition: mac-low.cc:1040
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:2760
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
control how a packet is transmitted.
bool IsCfpoll(void) const
Return true if the Type/Subtype is one of the possible CF-Poll headers.
void SetCtsToSelfSupported(bool enable)
Enable or disable CTS-to-self capability.
Definition: mac-low.cc:311
QueueEdcas m_edca
EDCA queues.
Definition: mac-low.h:909
void NormalAckTimeout(void)
Event handler when normal ACK timeout occurs.
Definition: mac-low.cc:1383
void SetBasicBlockAckTimeout(Time blockAckTimeout)
Set Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:299
bool IsAmsduSupported(void) const
Return whether A-MSDU capability is supported.
BlockAckCaches m_bAckCaches
block ack caches
Definition: mac-low.h:906
Time timestamp
the timestamp
Definition: mac-low.h:840
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:150
Time CalculateTxDuration(uint32_t size, WifiTxVector txVector, uint16_t frequency)
Definition: wifi-phy.cc:2301
void NotifyOn(void)
Notify listeners that we went to switch on.
Definition: mac-low.cc:88
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
WifiTxVector m_currentTxVector
TXVECTOR used for the current packet transmission.
Definition: mac-low.h:914
void DestroyBlockAckAgreement(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2019
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:874
Time m_lastNavDuration
The duration of the latest NAV.
Definition: mac-low.h:883
uint32_t GetSerializedSize(void) const
DcfManagers m_dcfManagers
List of DcfManager.
Definition: mac-low.h:851
NS_ASSERT_MSG(false,"Ipv4AddressGenerator::MaskToIndex(): Impossible")
std::pair< Ptr< Packet >, WifiMacHeader > BufferedPacket
buffered packet typedef
Definition: mac-low.h:893
void SendCtsToSelf(void)
Send CTS for a CTS-to-self mechanism.
Definition: mac-low.cc:1652
bool m_ctsToSelfSupported
Flag whether CTS-to-self is supported.
Definition: mac-low.h:911
tuple phy
Definition: third.py:86
void SendAckAfterData(Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
Send ACK after receiving DATA.
Definition: mac-low.cc:1872
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1375
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
#define max(a, b)
Definition: 80211b.c:45
void CreateBlockAckAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address originator, uint16_t startingSeq)
Definition: mac-low.cc:1977
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
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:43
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1031
receive notifications about phy events.
void CtsTimeout(void)
Event handler when CTS timeout occurs.
Definition: mac-low.cc:1368
void SendDelbaFrame(Mac48Address addr, uint8_t tid, bool byOriginator)
Sends DELBA frame to cancel a block ack agreement with sta addressed by addr for tid tid...
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:1853
void SendBlockAckAfterAmpdu(uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector, double rxSnr)
Invoked after an A-MPDU has been received.
Definition: mac-low.cc:2188
std::map< AgreementKey, BlockAckCache >::iterator BlockAckCachesI
block ack caches iterator typedef
Definition: mac-low.h:903
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:1067
void SetAckTimeout(Time ackTimeout)
Set ACK timeout of this MacLow.
Definition: mac-low.cc:293
static TypeId GetTypeId(void)
Register this type.
Definition: mac-low.cc:132
indicates whether the socket has a priority set.
Definition: socket.h:1303
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:28
Time GetRifs(void) const
Return Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:402
HT PHY (Clause 20)
Definition: wifi-mode.h:58
void NavCounterResetCtsMissed(Time rtsEndRxTime)
Reset NAV after CTS was missed when the NAV was setted with RTS.
Definition: mac-low.cc:1182
Ptr< WifiRemoteStationManager > m_stationManager
Pointer to WifiRemoteStationManager (rate control)
Definition: mac-low.h:830
bool IsQosBlockAck(void) const
Return if the QoS ACK policy is Block ACK.
Headers for Block ack response.
Definition: ctrl-headers.h:190
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
Mac48Address GetAddress(void) const
Return the MAC address of this MacLow.
Definition: mac-low.cc:365
void SendDataAfterCts(Time duration)
Send DATA after receiving CTS.
Definition: mac-low.cc:1753
Agreements m_bAckAgreements
block ack agreements
Definition: mac-low.h:905
Ptr< WifiMacQueue > m_aggregateQueue[8]
Queues per TID used for MPDU aggregation.
Definition: mac-low.h:912
uint16_t GetStartingSequenceControl(void) const
Return the starting sequence control.
void SendMpdu(Ptr< const Packet > packet, WifiTxVector txVector, MpduType mpdutype)
Forward the MPDU down to WifiPhy for transmission.
Definition: mac-low.cc:1361
The aim of the AmpduTag is to provide means for a MAC to specify that a packet includes A-MPDU since ...
Definition: ampdu-tag.h:36
WifiTxVector GetAckTxVectorForData(Mac48Address to, WifiMode dataTxMode) const
Return a TXVECTOR for the Block ACK frame given the destination and the mode of the DATA used by the ...
Definition: mac-low.cc:1085
bool IsMgt(void) const
Return true if the Type is Management.
void NotifySwitchingStartNow(Time duration)
Definition: mac-low.cc:618
void NotifyOff(void)
Notify listeners that we went to switch off.
Definition: mac-low.cc:81
Time m_slotTime
Slot duration.
Definition: mac-low.h:878
bool m_promisc
Flag if the device is operating in promiscuous mode.
Definition: mac-low.h:885
void NotifyRxStart(Time duration)
Definition: mac-low.cc:58
WifiMacHeader hdr
the header
Definition: mac-low.h:839
void CancelAllEvents(void)
Cancel all scheduled events.
Definition: mac-low.cc:190
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
buffered packet iterator typedef
Definition: mac-low.h:894
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
void BlockAckTimeout(void)
Event handler when block ACK timeout occurs.
Definition: mac-low.cc:1420
void NotifyCtsTimeoutStartNow(Time duration)
Notify DcfManagerthat CTS timer should be started for the given duration.
Definition: mac-low.cc:1238
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
void RegisterDcf(Ptr< DcfManager > dcf)
Definition: mac-low.cc:439
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.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
void SuperFastAckTimeout(void)
Event handler when super fast ACK timeout occurs.
Definition: mac-low.cc:1434
void SetBssid(Mac48Address ad)
Set the Basic Service Set Identification.
Definition: mac-low.cc:353
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
EventId m_waitIfsEvent
Wait for IFS event.
Definition: mac-low.h:862
void ReceiveOk(Ptr< Packet > packet, double rxSnr, WifiTxVector txVector, bool ampduSubframe)
Definition: mac-low.cc:664
void EnableAck(void)
Wait ACKTimeout for an ACK.
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:1125
EventId m_normalAckTimeoutEvent
Normal ACK timeout event.
Definition: mac-low.h:853
void StartDataTxTimers(WifiTxVector dataTxVector)
Start a DATA timer by scheduling appropriate ACK timeout.
Definition: mac-low.cc:1515
bool IsBasic(void) const
Check if the current ACK policy is basic (i.e.
void NotifyWakeup(void)
Notify listeners that we woke up.
Definition: mac-low.cc:85
void SetType(BlockAckType type)
Set the block ACK type.
void NotifyCtsTimeoutResetNow()
Notify DcfManager that CTS timer should be resetted.
Definition: mac-low.cc:1247
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:146
uint32_t RemoveTrailer(Trailer &trailer)
Remove a deserialized trailer from the internal buffer.
Definition: packet.cc:318
an EUI-48 address
Definition: mac48-address.h:43
Ptr< const Packet > packet
the packet
Definition: mac-low.h:838
Time GetLastRxStartTime(void) const
Return the start time of the last received packet.
Definition: wifi-phy.cc:3642
bool HasVhtSupported(void) const
Return whether the device has VHT capability support enabled.
void NotifyTxStart(Time duration, double txPowerDbm)
Definition: mac-low.cc:67
void SendBlockAckResponse(const CtrlBAckResponseHeader *blockAck, Mac48Address originator, bool immediate, Time duration, WifiMode blockAckReqTxMode, double rxSnr)
This method creates block ack frame with header equals to blockAck and start its transmission.
Definition: mac-low.cc:2127
Time m_ackTimeout
ACK timeout duration.
Definition: mac-low.h:873
uint8_t GetTid(Ptr< const Packet > packet, const WifiMacHeader hdr)
Extraction operator for TypeId.
Definition: qos-utils.cc:95
bool NeedRts(void) const
Check if the current packet should be sent with a RTS protection.
Definition: mac-low.cc:589
void FastAckTimeout(void)
Event handler when fast ACK timeout occurs (idle).
Definition: mac-low.cc:1402
void DisableRts(void)
Do not send rts and wait for cts before sending data.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:249
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:858
void RxCompleteBufferedPacketsWithSmallerSequence(uint16_t seq, Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2035
void SendCtsAfterRts(Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
Send CTS after receiving RTS.
Definition: mac-low.cc:1721
Time m_basicBlockAckTimeout
Basic block ACK timeout duration.
Definition: mac-low.h:874
bool IsStateTx(void) const
Definition: wifi-phy.cc:3612
uint16_t GetTimeout(void) const
Return the timeout.
uint8_t GetTid(void) const
Return the Traffic ID (TID).
void FlushAggregateQueue(uint8_t tid)
This function is called to flush the aggregate queue, which is used for A-MPDU.
Definition: mac-low.cc:2738
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
Time m_sifs
Short Interframe Space (SIFS) duration.
Definition: mac-low.h:877
const char * GetTypeString(void) const
Return a string corresponds to the header type.
bool HasHtSupported(void) const
Return whether the device has HT capability support enabled.
Time GetSlotTime(void) const
Return slot duration of this MacLow.
Definition: mac-low.cc:409
WifiMacHeader m_lastReceivedHdr
Header of the last received packet.
Definition: mac-low.h:869
void SetDelayedBlockAck(void)
Set Block ACK policy to delayed ACK.
WifiPreamble GetPreambleType(void) const
void NotifySleep(void)
Notify listeners that we went to sleep.
Definition: mac-low.cc:77
uint32_t GetCtsSize(void)
Return the total CTS size (including FCS trailer).
Definition: wifi-utils.cc:138
Time m_lastNavStart
The time when the latest NAV started.
Definition: mac-low.h:882
EventId m_inactivityEvent
inactivity event
bool NeedCtsToSelf(WifiTxVector txVector)
Return if we need to do Cts-to-self before sending a DATA.
void ReceiveError(Ptr< Packet > packet, double rxSnr)
Definition: mac-low.cc:604
void SetAmsduSupport(bool supported)
Enable or disable A-MSDU support.
WifiTxVector GetRtsTxVector(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return a TXVECTOR for the RTS frame given the destination.
Definition: mac-low.cc:1047
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:1054
handle RTS/CTS/DATA/ACK transactions.
Definition: mac-low.h:51
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:406
std::vector< Ptr< DcfManager > >::const_iterator DcfManagersCI
typedef for an iterator for a list of DcfManager.
Definition: mac-low.h:846
EventId m_sendDataEvent
Event to send DATA.
Definition: mac-low.h:861
void RegisterListener(WifiPhyListener *listener)
Definition: wifi-phy.cc:418
bool ReceiveMpdu(Ptr< Packet > packet, WifiMacHeader hdr)
Definition: mac-low.cc:1904
bool HasHeSupported(void) const
Return whether the device has HE capability support enabled.
void NotifyRxEndError(void)
We have received the last bit of a packet for which NotifyRxStart was invoked first and...
Definition: mac-low.cc:64
MacLowTransmissionParameters m_txParams
Transmission parameters of the current packet.
Definition: mac-low.h:870
void SetRifs(Time rifs)
Set Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:347
void DoDispose(void)
Destructor implementation.
Definition: mac-low.cc:161
void NotifyAckTimeoutResetNow()
Notify DcfManager that ACK timer should be resetted.
Definition: mac-low.cc:1229
WifiTxVector GetDataTxVector(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
TimeWithUnit As(const enum Unit unit) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:388
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:1073
bool IsData(void) const
Return true if the Type is DATA.
Mac48Address m_self
Address of this MacLow (Mac48Address)
Definition: mac-low.h:871
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:856
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:69
bool IsNavZero(void) const
Check if NAV is zero.
Definition: mac-low.cc:1646
void EnableRts(void)
Send a RTS, and wait CTSTimeout for a CTS.
Time GetBlockAckDuration(WifiTxVector blockAckReqTxVector, 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:1023
void NotifyAckTimeoutStartNow(Time duration)
Notify DcfManager that ACK timer should be started for the given duration.
Definition: mac-low.cc:1220
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:335
Ptr< Packet > m_currentPacket
Current packet transmitted/to be transmitted.
Definition: mac-low.h:866
Time GetSifs(void) const
Return Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:395
bool NeedCtsToSelf(void) const
Check if CTS-to-self mechanism should be used for the current packet.
Definition: mac-low.cc:597
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:859
bool StopMpduAggregation(Ptr< const Packet > peekedPacket, WifiMacHeader peekedHdr, Ptr< Packet > aggregatedPacket, uint16_t size) const
Definition: mac-low.cc:2393
Implement the header for management frames of type add block ack response.
Definition: mgt-headers.h:1115
bool GetRifsPermitted(void) const
Return whether the device can use RIFS.
ns3::MacLow * m_macLow
the MAC
Definition: mac-low.cc:93
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:269
uint32_t GetBlockAckSize(BlockAckType type)
Return the total Block ACK size (including FCS trailer).
Definition: wifi-utils.cc:108
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1007
std::map< AgreementKey, AgreementValue >::iterator AgreementsI
agreements iterator
Definition: mac-low.h:900
EventId m_endTxNoAckEvent
Event for finishing transmission that does not require ACK.
Definition: mac-low.h:863
bool IsStateOff(void) const
Definition: wifi-phy.cc:3630
bool GetCtsToSelfSupported() const
Return whether CTS-to-self capability is supported.
Definition: mac-low.cc:317
void ReportRxOk(Mac48Address address, const WifiMacHeader *header, double rxSnr, WifiMode txMode)
void NotifyRxEndOk(void)
We have received the last bit of a packet for which NotifyRxStart was invoked first and...
Definition: mac-low.cc:61
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:323
void SetImmediateBlockAck(void)
Set Block ACK policy to immediate ACK.
Time GetAckTimeout(void) const
Return ACK timeout of this MacLow.
Definition: mac-low.cc:371
void DisableNextData(void)
Do not attempt to send data burst after current transmission.
void SendDataPacket(void)
Send DATA packet, which can be DATA-ACK or RTS-CTS-DATA-ACK transaction.
Definition: mac-low.cc:1589
void SetTimeout(uint16_t timeout)
Set timeout.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1023
WifiMacHeader m_currentHdr
Header of the current transmitted packet.
Definition: mac-low.h:867
void SetAddress(Mac48Address ad)
Set MAC address of this MacLow.
Definition: mac-low.cc:287
bool IsCts(void) const
Return true if the header is a CTS header.
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
WifiTxVector GetRtsTxVector(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
A base class which provides memory management and object aggregation.
Definition: object.h:87
void WaitIfsAfterEndTxFragment(void)
Event handler that is usually scheduled to fired at the appropriate time after completing transmissio...
Definition: mac-low.cc:1839
PhyMacLowListener(ns3::MacLow *macLow)
Create a PhyMacLowListener for the given MacLow.
Definition: mac-low.cc:51
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:487
Time m_compressedBlockAckTimeout
Compressed block ACK timeout duration.
Definition: mac-low.h:875
WifiMode GetMode(void) const
void SetRemainingNbOfMpdus(uint8_t nbofmpdus)
Definition: ampdu-tag.cc:53
WifiTxVector GetBlockAckTxVector(Mac48Address address, WifiMode dataMode)
The MPDU is part of an A-MPDU, but is not the last aggregate.
Definition: wifi-phy.h:66
bool IsRts(void) const
Return true if the header is a RTS header.
Headers for Block ack request.
Definition: ctrl-headers.h:50
bool IsAmpdu(Ptr< const Packet > packet, const WifiMacHeader hdr)
Checks if the given packet will be aggregated to an A-MPDU or not.
Definition: mac-low.cc:445
bool IsAck(void) const
Return true if the header is an ACK header.
void InsertInTxQueue(Ptr< const Packet > packet, const WifiMacHeader &hdr, Time tStamp, uint8_t tid)
Insert in a temporary queue.
Definition: mac-low.cc:2749
virtual ~PhyMacLowListener()
Definition: mac-low.cc:55
void ResetPhy(void)
Remove WifiPhy associated with this MacLow.
Definition: mac-low.cc:272
void DisableAck(void)
Do not wait for Ack after data transmission.
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
agreement value typedef
Definition: mac-low.h:897
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:1079
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
bool IsStateIdle(void) const
Definition: wifi-phy.cc:3600
Time GetBasicBlockAckTimeout() const
Return Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:377
a unique identifier for an interface.
Definition: type-id.h:58
WifiTxVector GetAckTxVector(Mac48Address address, WifiMode dataMode)
BlockAckCache cache.
MpduType
This enumeration defines the type of an MPDU.
Definition: wifi-phy.h:61
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:914
Time GetRemainingAmpduDuration(void) const
Definition: ampdu-tag.cc:96
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:880
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:38
Ptr< T > Copy(Ptr< T > object)
Return a deep copy of a Ptr.
Definition: ptr.h:688
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:1061
Introspection did not find any typical Config paths.
Definition: snr-tag.h:34
bool StoreMpduIfNeeded(Ptr< Packet > packet, WifiMacHeader hdr)
Definition: mac-low.cc:1948
HE PHY (Clause 26)
Definition: wifi-mode.h:62
virtual ~MacLow()
Definition: mac-low.cc:125
A struct for packet, Wifi header, and timestamp.item structure.
Definition: mac-low.h:836
Ptr< WifiPhy > m_phy
Pointer to WifiPhy (actually send/receives frames)
Definition: mac-low.h:829
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > manager)
Set up WifiRemoteStationManager associated with this MacLow.
Definition: mac-low.cc:281
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:305
Implements the IEEE 802.11 MAC trailer.
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:888
void RegisterEdcaForAc(AcIndex ac, Ptr< EdcaTxopN > edca)
Definition: mac-low.cc:2298
uint32_t GetSerializedSize(void) const
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:1453
void RxCompleteBufferedPacketsUntilFirstLost(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2098
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
void SetRemainingAmpduDuration(Time duration)
Definition: ampdu-tag.cc:60
void SetQosAckPolicy(QosAckPolicy policy)
Set the QoS ACK policy in the QoS control field.