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  * Stefano Avallone <stavallo@unina.it>
22  */
23 
24 #include "ns3/simulator.h"
25 #include "ns3/log.h"
26 #include "mac-low.h"
27 #include "qos-txop.h"
28 #include "snr-tag.h"
29 #include "ampdu-tag.h"
30 #include "wifi-mac-queue.h"
31 #include "wifi-psdu.h"
32 #include "wifi-utils.h"
33 #include "ctrl-headers.h"
34 #include "mgt-headers.h"
36 #include "mpdu-aggregator.h"
37 #include "msdu-aggregator.h"
38 #include "ampdu-subframe-header.h"
39 #include "wifi-phy-listener.h"
40 #include "wifi-mac-trailer.h"
41 #include "wifi-phy.h"
42 #include "wifi-net-device.h"
43 #include "wifi-mac.h"
44 #include <algorithm>
46 
47 #undef NS_LOG_APPEND_CONTEXT
48 #define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_self << "] "
49 
50 namespace ns3 {
51 
52 NS_LOG_COMPONENT_DEFINE ("MacLow");
53 
58 {
59 public:
66  : m_macLow (macLow)
67  {
68  }
69  virtual ~PhyMacLowListener ()
70  {
71  }
72  void NotifyRxStart (Time duration)
73  {
74  }
75  void NotifyRxEndOk (void)
76  {
77  }
78  void NotifyRxEndError (void)
79  {
80  }
81  void NotifyTxStart (Time duration, double txPowerDbm)
82  {
83  }
84  void NotifyMaybeCcaBusyStart (Time duration)
85  {
86  }
87  void NotifySwitchingStart (Time duration)
88  {
90  }
91  void NotifySleep (void)
92  {
94  }
95  void NotifyOff (void)
96  {
98  }
99  void NotifyWakeup (void)
100  {
101  }
102  void NotifyOn (void)
103  {
104  }
105 
106 private:
108 };
109 
110 
112  : m_msduAggregator (0),
113  m_mpduAggregator (0),
114  m_normalAckTimeoutEvent (),
115  m_blockAckTimeoutEvent (),
116  m_ctsTimeoutEvent (),
117  m_sendCtsEvent (),
118  m_sendAckEvent (),
119  m_sendDataEvent (),
120  m_waitIfsEvent (),
121  m_endTxNoAckEvent (),
122  m_currentPacket (0),
123  m_currentTxop (0),
124  m_lastNavStart (Seconds (0)),
125  m_lastNavDuration (Seconds (0)),
126  m_cfpStart (Seconds (0)),
127  m_lastBeacon (Seconds (0)),
128  m_cfpForeshortening (Seconds (0)),
129  m_promisc (false),
130  m_phyMacLowListener (0),
131  m_ctsToSelfSupported (false),
132  m_cfAckInfo ()
133 {
134  NS_LOG_FUNCTION (this);
135 }
136 
138 {
139  NS_LOG_FUNCTION (this);
140 }
141 
142 /* static */
143 TypeId
145 {
146  static TypeId tid = TypeId ("ns3::MacLow")
147  .SetParent<Object> ()
148  .SetGroupName ("Wifi")
149  .AddConstructor<MacLow> ()
150  ;
151  return tid;
152 }
153 
154 void
156 {
158  phy->RegisterListener (m_phyMacLowListener);
159 }
160 
161 void
163 {
164  if (m_phyMacLowListener != 0 )
165  {
166  phy->UnregisterListener (m_phyMacLowListener);
167  delete m_phyMacLowListener;
169  }
170 }
171 
172 void
174 {
175  NS_LOG_FUNCTION (this);
184  m_msduAggregator = 0;
185  m_mpduAggregator = 0;
186  m_phy = 0;
187  m_stationManager = 0;
188  if (m_phyMacLowListener != 0)
189  {
190  delete m_phyMacLowListener;
192  }
193 }
194 
195 void
197 {
198  NS_LOG_FUNCTION (this);
199  bool oneRunning = false;
201  {
203  oneRunning = true;
204  }
206  {
208  oneRunning = true;
209  }
211  {
213  oneRunning = true;
214  }
215  if (m_sendCtsEvent.IsRunning ())
216  {
218  oneRunning = true;
219  }
220  if (m_sendAckEvent.IsRunning ())
221  {
223  oneRunning = true;
224  }
225  if (m_sendDataEvent.IsRunning ())
226  {
228  oneRunning = true;
229  }
230  if (m_waitIfsEvent.IsRunning ())
231  {
233  oneRunning = true;
234  }
236  {
238  oneRunning = true;
239  }
240  if (oneRunning && m_currentTxop != 0)
241  {
242  m_currentTxop->Cancel ();
243  m_currentTxop = 0;
244  }
245 }
246 
247 void
249 {
250  m_phy = phy;
254 }
255 
257 MacLow::GetPhy (void) const
258 {
259  return m_phy;
260 }
261 
262 void
264 {
265  m_phy->SetReceiveOkCallback (MakeNullCallback<void, Ptr<WifiPsdu>, double, WifiTxVector, std::vector<bool>> ());
268  m_phy = 0;
269 }
270 
272 MacLow::GetEdca (uint8_t tid) const
273 {
274  auto it = m_edca.find (QosUtilsMapTidToAc (tid));
275  NS_ASSERT (it != m_edca.end ());
276  return it->second;
277 }
278 
279 void
281 {
282  m_mac = mac;
283 }
284 
285 void
287 {
288  m_stationManager = manager;
289 }
290 
293 {
294  return m_msduAggregator;
295 }
296 
299 {
300  return m_mpduAggregator;
301 }
302 
303 void
305 {
306  NS_LOG_FUNCTION (this << aggr);
307  m_msduAggregator = aggr;
308 }
309 
310 void
312 {
313  NS_LOG_FUNCTION (this << aggr);
314  m_mpduAggregator = aggr;
315 }
316 
317 void
319 {
320  m_self = ad;
321 }
322 
323 void
325 {
326  m_ackTimeout = ackTimeout;
327 }
328 
329 void
331 {
332  m_basicBlockAckTimeout = blockAckTimeout;
333 }
334 
335 void
337 {
338  m_compressedBlockAckTimeout = blockAckTimeout;
339 }
340 
341 void
343 {
344  m_ctsToSelfSupported = enable;
345 }
346 
347 bool
349 {
350  return m_ctsToSelfSupported;
351 }
352 
353 void
355 {
356  m_ctsTimeout = ctsTimeout;
357 }
358 
359 void
361 {
362  m_sifs = sifs;
363 }
364 
365 void
367 {
368  m_slotTime = slotTime;
369 }
370 
371 void
373 {
374  m_pifs = pifs;
375 }
376 
377 void
379 {
380  m_rifs = rifs;
381 }
382 
383 void
385 {
386  m_beaconInterval = interval;
387 }
388 
389 void
391 {
392  m_cfpMaxDuration = cfpMaxDuration;
393 }
394 
395 void
397 {
398  m_bssid = bssid;
399 }
400 
401 void
403 {
404  m_promisc = true;
405 }
406 
408 MacLow::GetAddress (void) const
409 {
410  return m_self;
411 }
412 
413 Time
415 {
416  return m_ackTimeout;
417 }
418 
419 Time
421 {
422  return m_basicBlockAckTimeout;
423 }
424 
425 Time
427 {
429 }
430 
431 Time
433 {
434  return m_ctsTimeout;
435 }
436 
437 Time
438 MacLow::GetSifs (void) const
439 {
440  return m_sifs;
441 }
442 
443 Time
444 MacLow::GetRifs (void) const
445 {
446  return m_rifs;
447 }
448 
449 Time
451 {
452  return m_slotTime;
453 }
454 
455 Time
456 MacLow::GetPifs (void) const
457 {
458  return m_pifs;
459 }
460 
462 MacLow::GetBssid (void) const
463 {
464  return m_bssid;
465 }
466 
467 Time
469 {
470  return m_beaconInterval;
471 }
472 
473 Time
475 {
476  return m_cfpMaxDuration;
477 }
478 
479 bool
480 MacLow::IsPromisc (void) const
481 {
482  return m_promisc;
483 }
484 
485 void
487 {
488  m_rxCallback = callback;
489 }
490 
491 void
493 {
494  m_channelAccessManagers.push_back (dcf);
495 }
496 
497 void
500  Ptr<Txop> txop)
501 {
502  NS_LOG_FUNCTION (this << *mpdu << params << txop);
504  if (m_phy->IsStateOff ())
505  {
506  NS_LOG_DEBUG ("Cannot start TX because device is OFF");
507  return;
508  }
509  /* m_currentPacket is not NULL because someone started
510  * a transmission and was interrupted before one of:
511  * - ctsTimeout
512  * - sendDataAfterCTS
513  * expired. This means that one of these timers is still
514  * running. They are all cancelled below anyway by the
515  * call to CancelAllEvents (because of at least one
516  * of these two timers) which will trigger a call to the
517  * previous listener's cancel method.
518  *
519  * This typically happens because the high-priority
520  * QapScheduler has taken access to the channel from
521  * one of the Edca of the QAP.
522  */
523  m_currentPacket = Create<WifiPsdu> (mpdu, false);
524  const WifiMacHeader& hdr = mpdu->GetHeader ();
525  CancelAllEvents ();
526  m_currentTxop = txop;
527  m_txParams = params;
528  if (hdr.IsCtl ())
529  {
531  }
532  else
533  {
535  }
536 
537  /* The packet received by this function can be any of the following:
538  * (a) a management frame dequeued from the Txop
539  * (b) a non-QoS data frame dequeued from the Txop
540  * (c) a non-broadcast QoS Data frame peeked or dequeued from a QosTxop
541  * (d) a broadcast QoS data or DELBA Request frame dequeued from a QosTxop
542  * (e) a BlockAckReq or ADDBA Request frame
543  * (f) a fragment of non-QoS/QoS Data frame dequeued from the Txop/QosTxop
544  */
545  if (hdr.IsQosData () && !hdr.GetAddr1 ().IsBroadcast ()
546  && !hdr.IsMoreFragments () && hdr.GetFragmentNumber () == 0)
547  {
548  // We get here if the received packet is a non-broadcast QoS data frame
549  uint8_t tid = hdr.GetQosTid ();
550  Ptr<QosTxop> qosTxop = m_edca.find (QosUtilsMapTidToAc (tid))->second;
551 
552  // if a TXOP limit exists, compute the remaining TXOP duration
553  Time txopLimit = Time::Min ();
555  {
557  NS_ASSERT (txopLimit.IsPositive ());
558  }
559 
560  // QosTxop may send us a peeked frame
561  Ptr<const WifiMacQueueItem> tmp = qosTxop->PeekNextFrame ();
562  bool isPeeked = (tmp != 0 && tmp->GetPacket () == mpdu->GetPacket ());
563 
564  Ptr<WifiMacQueueItem> newMpdu;
565  // If the frame has been peeked, dequeue it if it meets the size and duration constraints
566  if (isPeeked)
567  {
568  newMpdu = qosTxop->DequeuePeekedFrame (mpdu, m_currentTxVector, true, 0, txopLimit);
569  }
570  else if (IsWithinSizeAndTimeLimits (mpdu, m_currentTxVector, 0, txopLimit))
571  {
572  newMpdu = mpdu;
573  }
574 
575  if (newMpdu == 0)
576  {
577  // if the frame has been dequeued, then there is no BA agreement with the
578  // receiver (otherwise the frame would have been peeked). Hence, the frame
579  // has been sent under Normal Ack policy, not acknowledged and now retransmitted.
580  // If we cannot send it now, let the QosTxop retransmit it again.
581  // If the frame has been just peeked, reset the current packet at QosTxop.
582  if (isPeeked)
583  {
584  qosTxop->UpdateCurrentPacket (Create<WifiMacQueueItem> (nullptr, WifiMacHeader ()));
585  }
586  return;
587  }
588  // Update the current packet at QosTxop, given that A-MSDU aggregation may have
589  // been performed on the peeked frame
590  qosTxop->UpdateCurrentPacket (newMpdu);
591 
592  //Perform MPDU aggregation if possible
593  std::vector<Ptr<WifiMacQueueItem>> mpduList;
594  if (m_mpduAggregator != 0)
595  {
596  mpduList = m_mpduAggregator->GetNextAmpdu (newMpdu, m_currentTxVector, txopLimit);
597  }
598 
599  if (mpduList.size () > 1)
600  {
601  m_currentPacket = Create<WifiPsdu> (mpduList);
602 
603  NS_LOG_DEBUG ("tx unicast A-MPDU containing " << mpduList.size () << " MPDUs");
604  qosTxop->SetAmpduExist (hdr.GetAddr1 (), true);
605  }
608  {
609  // VHT/HE single MPDU
610  m_currentPacket = Create<WifiPsdu> (newMpdu, true);
611 
612  NS_LOG_DEBUG ("tx unicast S-MPDU with sequence number " << hdr.GetSequenceNumber ());
613  qosTxop->SetAmpduExist (hdr.GetAddr1 (), true);
614  }
615  else // HT
616  {
617  m_currentPacket = Create<WifiPsdu> (newMpdu, false);
618  }
619 
620  // A QoS Txop must have an installed ack policy selector
621  NS_ASSERT (qosTxop->GetAckPolicySelector () != 0);
622  qosTxop->GetAckPolicySelector ()->UpdateTxParams (m_currentPacket, m_txParams);
623  qosTxop->GetAckPolicySelector ()->SetAckPolicy (m_currentPacket, m_txParams);
624  }
625 
626  NS_LOG_DEBUG ("startTx size=" << m_currentPacket->GetSize () <<
627  ", to=" << m_currentPacket->GetAddr1 () << ", txop=" << m_currentTxop);
628 
629  if (m_txParams.MustSendRts ())
630  {
631  SendRtsForPacket ();
632  }
633  else
634  {
636  {
637  SendCtsToSelf ();
638  }
639  else
640  {
641  SendDataPacket ();
642  }
643  }
644 
645  /* When this method completes, either we have taken ownership of the medium or the device switched off in the meantime. */
647 }
648 
649 bool
651 {
652  WifiTxVector dataTxVector = GetDataTxVector (*m_currentPacket->begin ());
653  return m_stationManager->NeedCtsToSelf (dataTxVector);
654 }
655 
656 bool
658  uint32_t ampduSize, Time ppduDurationLimit)
659 {
660  NS_ASSERT (mpdu != 0 && mpdu->GetHeader ().IsQosData ());
661 
662  return IsWithinSizeAndTimeLimits (mpdu->GetSize (), mpdu->GetHeader ().GetAddr1 (),
663  mpdu->GetHeader ().GetQosTid (), txVector,
664  ampduSize, ppduDurationLimit);
665 }
666 
667 bool
668 MacLow::IsWithinSizeAndTimeLimits (uint32_t mpduSize, Mac48Address receiver, uint8_t tid,
669  WifiTxVector txVector, uint32_t ampduSize, Time ppduDurationLimit)
670 {
671  NS_LOG_FUNCTION (this << mpduSize << receiver << +tid << txVector << ampduSize << ppduDurationLimit);
672 
673  if (ppduDurationLimit != Time::Min () && ppduDurationLimit.IsNegative ())
674  {
675  return false;
676  }
677 
678  WifiModulationClass modulation = txVector.GetMode ().GetModulationClass ();
679 
680  uint32_t maxAmpduSize = 0;
681  if (GetMpduAggregator ())
682  {
683  maxAmpduSize = GetMpduAggregator ()->GetMaxAmpduSize (receiver, tid, modulation);
684  }
685 
686  // If maxAmpduSize is null, then ampduSize must be null as well
687  NS_ASSERT (maxAmpduSize || ampduSize == 0);
688 
689  uint32_t ppduPayloadSize = mpduSize;
690 
691  // compute the correct size for A-MPDUs and S-MPDUs
692  if (ampduSize > 0 || modulation >= WIFI_MOD_CLASS_VHT)
693  {
694  ppduPayloadSize = GetMpduAggregator ()->GetSizeIfAggregated (mpduSize, ampduSize);
695  }
696 
697  if (maxAmpduSize > 0 && ppduPayloadSize > maxAmpduSize)
698  {
699  NS_LOG_DEBUG ("the frame does not meet the constraint on max A-MPDU size");
700  return false;
701  }
702 
703  // Get the maximum PPDU Duration based on the preamble type
704  Time maxPpduDuration = GetPpduMaxTime (txVector.GetPreambleType ());
705 
706  Time txTime = m_phy->CalculateTxDuration (ppduPayloadSize, txVector, m_phy->GetFrequency ());
707 
708  if ((ppduDurationLimit.IsStrictlyPositive () && txTime > ppduDurationLimit)
709  || (maxPpduDuration.IsStrictlyPositive () && txTime > maxPpduDuration))
710  {
711  NS_LOG_DEBUG ("the frame does not meet the constraint on max PPDU duration");
712  return false;
713  }
714 
715  return true;
716 }
717 
718 void
720 {
721  NS_LOG_FUNCTION (this << *psdu);
722  NS_LOG_DEBUG ("rx failed");
723  if (IsCfPeriod () && m_currentPacket->GetHeader (0).IsCfPoll ())
724  {
725  NS_ASSERT (m_currentTxop != 0);
727  }
728  else if (m_cfAckInfo.expectCfAck)
729  {
730  NS_ASSERT (m_currentTxop != 0);
731  Ptr<Txop> txop = m_currentTxop;
732  m_currentTxop = 0;
733  txop->MissedAck ();
734  }
735  m_cfAckInfo.expectCfAck = false;
736  return;
737 }
738 
739 void
741 {
742  NS_LOG_DEBUG ("switching channel. Cancelling MAC pending events");
744  CancelAllEvents ();
746  {
748  }
751  m_currentPacket = 0;
752  m_currentTxop = 0;
753 }
754 
755 void
757 {
758  NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
759  CancelAllEvents ();
761  {
763  }
766  m_currentPacket = 0;
767  m_currentTxop = 0;
768 }
769 
770 void
772 {
773  NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events");
774  CancelAllEvents ();
776  {
778  }
781  m_currentPacket = 0;
782  m_currentTxop = 0;
783 }
784 
785 void
786 MacLow::ReceiveOk (Ptr<WifiMacQueueItem> mpdu, double rxSnr, WifiTxVector txVector, bool ampduSubframe)
787 {
788  NS_LOG_FUNCTION (this << *mpdu << rxSnr << txVector);
789  /* An MPDU is received from the PHY.
790  * When we have handled this MPDU,
791  * we handle any packet present in the
792  * packet queue.
793  */
794  const WifiMacHeader& hdr = mpdu->GetHeader ();
795  Ptr<Packet> packet = mpdu->GetPacket ()->Copy ();
796 
797  bool isPrevNavZero = IsNavZero ();
798  NS_LOG_DEBUG ("duration/id=" << hdr.GetDuration ());
799  NotifyNav (packet, hdr);
800  if (hdr.IsRts ())
801  {
802  /* see section 9.2.5.7 802.11-1999
803  * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS
804  * period if the NAV at the STA receiving the RTS frame indicates that the medium is
805  * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle,
806  * that STA shall not respond to the RTS frame.
807  */
808  if (ampduSubframe)
809  {
810  NS_FATAL_ERROR ("Received RTS as part of an A-MPDU");
811  }
812  else
813  {
814  if (isPrevNavZero
815  && hdr.GetAddr1 () == m_self)
816  {
817  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
819  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
820  rxSnr, txVector.GetMode ());
823  hdr.GetAddr2 (),
824  hdr.GetDuration (),
825  txVector,
826  rxSnr);
827  }
828  else
829  {
830  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
831  }
832  }
833  }
834  else if (hdr.IsCts ()
835  && hdr.GetAddr1 () == m_self
837  && m_currentPacket != 0)
838  {
839  if (ampduSubframe)
840  {
841  NS_FATAL_ERROR ("Received CTS as part of an A-MPDU");
842  }
843 
844  NS_LOG_DEBUG ("received cts from=" << m_currentPacket->GetAddr1 ());
845 
846  SnrTag tag;
847  packet->RemovePacketTag (tag);
848  m_stationManager->ReportRxOk (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0),
849  rxSnr, txVector.GetMode ());
850  m_stationManager->ReportRtsOk (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0),
851  rxSnr, txVector.GetMode (), tag.Get ());
852 
858  hdr.GetDuration ());
859  }
860  else if (hdr.IsAck ()
861  && hdr.GetAddr1 () == m_self
864  {
865  NS_LOG_DEBUG ("receive ack from=" << m_currentPacket->GetAddr1 ());
866  SnrTag tag;
867  packet->RemovePacketTag (tag);
868  //When fragmentation is used, only update manager when the last fragment is acknowledged
869  if (!m_txParams.HasNextPacket ())
870  {
871  m_stationManager->ReportRxOk (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0),
872  rxSnr, txVector.GetMode ());
873  m_stationManager->ReportDataOk (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0),
874  rxSnr, txVector.GetMode (), tag.Get (),
875  m_currentPacket->GetSize ());
876  }
877  bool gotAck = false;
880  {
883  gotAck = true;
884  }
885  if (gotAck)
886  {
887  m_currentTxop->GotAck ();
888  }
889  if (m_txParams.HasNextPacket ())
890  {
892  {
894  }
895  else
896  {
898  }
899  }
900  else if (m_currentPacket->GetHeader (0).IsQosData () && m_currentTxop->IsQosTxop () &&
902  {
904  {
906  }
907  else
908  {
910  }
911  }
912  else if (m_currentTxop->IsQosTxop ())
913  {
915  }
916  }
917  else if (hdr.IsBlockAck () && hdr.GetAddr1 () == m_self
920  {
921  NS_LOG_DEBUG ("got block ack from " << hdr.GetAddr2 ());
922  SnrTag tag;
923  packet->RemovePacketTag (tag);
924  CtrlBAckResponseHeader blockAck;
925  packet->RemoveHeader (blockAck);
928  m_currentTxop->GotBlockAck (&blockAck, hdr.GetAddr2 (), rxSnr, txVector.GetMode (), tag.Get ());
929  // start next packet if TXOP remains, otherwise contend for accessing the channel again
932  {
934  {
936  }
937  else
938  {
940  }
941  }
942  else if (m_currentTxop->IsQosTxop ())
943  {
945  }
946  }
947  else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
948  {
949  CtrlBAckRequestHeader blockAckReq;
950  packet->RemoveHeader (blockAckReq);
951  if (!blockAckReq.IsMultiTid ())
952  {
953  uint8_t tid = blockAckReq.GetTidInfo ();
954  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), tid));
955  if (it != m_bAckAgreements.end ())
956  {
957  //Update block ack cache
958  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), tid));
959  NS_ASSERT (i != m_bAckCaches.end ());
960  (*i).second.UpdateWithBlockAckReq (blockAckReq.GetStartingSequence ());
961 
962  //NS_ASSERT (m_sendAckEvent.IsExpired ());
964  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
965  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
966  if ((*it).second.first.IsImmediateBlockAck ())
967  {
968  NS_LOG_DEBUG ("rx blockAckRequest/sendImmediateBlockAck from=" << hdr.GetAddr2 ());
971  blockAckReq,
972  hdr.GetAddr2 (),
973  hdr.GetDuration (),
974  txVector.GetMode (),
975  rxSnr);
976  }
977  else
978  {
979  NS_FATAL_ERROR ("Delayed block ack not supported.");
980  }
981  }
982  else
983  {
984  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
985  }
986  }
987  else
988  {
989  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
990  }
991  }
992  else if (hdr.IsCtl ())
993  {
994  if (hdr.IsCfEnd ())
995  {
996  NS_LOG_DEBUG ("rx CF-END ");
997  m_cfpStart = NanoSeconds (0);
999  {
1000  NS_ASSERT (m_currentTxop != 0);
1001  if (hdr.IsCfAck ())
1002  {
1003  m_currentTxop->GotAck ();
1004  }
1005  else
1006  {
1008  }
1009  }
1010  if (m_currentTxop != 0)
1011  {
1012  m_currentTxop->GotCfEnd ();
1013  }
1014  m_cfAckInfo.expectCfAck = false;
1015  }
1016  else
1017  {
1018  NS_LOG_DEBUG ("rx drop " << hdr.GetTypeString ());
1019  }
1020  }
1021  else if (hdr.GetAddr1 () == m_self)
1022  {
1023  if (hdr.IsCfPoll ())
1024  {
1026  if (m_cfAckInfo.expectCfAck && !hdr.IsCfAck ())
1027  {
1028  NS_ASSERT (m_currentTxop != 0);
1029  Ptr<Txop> txop = m_currentTxop;
1030  m_currentTxop = 0;
1031  txop->MissedAck ();
1032  m_cfAckInfo.expectCfAck = false;
1033  }
1034  }
1035  m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
1036  rxSnr, txVector.GetMode ());
1037  if (hdr.IsQosData () && ReceiveMpdu (mpdu))
1038  {
1039  /* From section 9.10.4 in IEEE 802.11:
1040  Upon the receipt of a QoS data frame from the originator for which
1041  the Block Ack agreement exists, the recipient shall buffer the MSDU
1042  regardless of the value of the Ack Policy subfield within the
1043  QoS Control field of the QoS data frame. */
1044  if (hdr.IsQosAck () && !ampduSubframe)
1045  {
1046  NS_LOG_DEBUG ("rx QoS unicast/sendAck from=" << hdr.GetAddr2 ());
1047  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1048 
1049  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (),
1050  hdr.GetAddr2 (), hdr.GetQosTid ());
1054  &MacLow::SendAckAfterData, this,
1055  hdr.GetAddr2 (),
1056  hdr.GetDuration (),
1057  txVector.GetMode (),
1058  rxSnr);
1059  }
1060  else if (hdr.IsQosBlockAck ())
1061  {
1062  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1063  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
1064  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
1065  }
1066  return;
1067  }
1068  else if (hdr.IsQosData () && hdr.IsQosBlockAck ())
1069  {
1070  /* This happens if a packet with ack policy Block Ack is received and a block ack
1071  agreement for that packet doesn't exist.
1072 
1073  From section 11.5.3 in IEEE 802.11e:
1074  When a recipient does not have an active Block ack for a TID, but receives
1075  data MPDUs with the Ack Policy subfield set to Block Ack, it shall discard
1076  them and shall send a DELBA frame using the normal access
1077  mechanisms. */
1078  AcIndex ac = QosUtilsMapTidToAc (hdr.GetQosTid ());
1079  m_edca[ac]->SendDelbaFrame (hdr.GetAddr2 (), hdr.GetQosTid (), false);
1080  return;
1081  }
1082  else if (hdr.IsQosData () && hdr.IsQosNoAck ())
1083  {
1084  if (ampduSubframe)
1085  {
1086  NS_LOG_DEBUG ("rx Ampdu with No Ack Policy from=" << hdr.GetAddr2 ());
1087  }
1088  else
1089  {
1090  NS_LOG_DEBUG ("rx unicast/noAck from=" << hdr.GetAddr2 ());
1091  }
1092  }
1093  else if (hdr.IsData () || hdr.IsMgt ())
1094  {
1095  if (hdr.IsProbeResp ())
1096  {
1097  // Apply SNR tag for probe response quality measurements
1098  SnrTag tag;
1099  tag.Set (rxSnr);
1100  packet->AddPacketTag (tag);
1101  mpdu = Create<WifiMacQueueItem> (packet, hdr);
1102  }
1103  if (hdr.IsMgt () && ampduSubframe)
1104  {
1105  NS_FATAL_ERROR ("Received management packet as part of an A-MPDU");
1106  }
1107  else
1108  {
1109  if (IsCfPeriod ())
1110  {
1111  if (hdr.HasData ())
1112  {
1113  m_cfAckInfo.appendCfAck = true;
1114  m_cfAckInfo.address = hdr.GetAddr2 ();
1115  }
1116  }
1117  else
1118  {
1119  NS_LOG_DEBUG ("rx unicast/sendAck from=" << hdr.GetAddr2 ());
1122  &MacLow::SendAckAfterData, this,
1123  hdr.GetAddr2 (),
1124  hdr.GetDuration (),
1125  txVector.GetMode (),
1126  rxSnr);
1127  }
1128  }
1129  }
1130  goto rxPacket;
1131  }
1132  else if (hdr.GetAddr1 ().IsGroup ())
1133  {
1134  if (ampduSubframe)
1135  {
1136  NS_FATAL_ERROR ("Received group addressed packet as part of an A-MPDU");
1137  }
1138  else
1139  {
1140  if (hdr.IsData () || hdr.IsMgt ())
1141  {
1142  NS_LOG_DEBUG ("rx group from=" << hdr.GetAddr2 ());
1143  if (hdr.IsBeacon ())
1144  {
1145  // Apply SNR tag for beacon quality measurements
1146  SnrTag tag;
1147  tag.Set (rxSnr);
1148  packet->AddPacketTag (tag);
1149  mpdu = Create<WifiMacQueueItem> (packet, hdr);
1150  }
1151  goto rxPacket;
1152  }
1153  }
1154  }
1155  else if (m_promisc)
1156  {
1157  NS_ASSERT (hdr.GetAddr1 () != m_self);
1158  if (hdr.IsData ())
1159  {
1160  goto rxPacket;
1161  }
1162  }
1163  else
1164  {
1165  if (m_cfAckInfo.expectCfAck && hdr.IsCfAck ())
1166  {
1167  m_cfAckInfo.expectCfAck = false;
1168  NS_ASSERT (m_currentTxop != 0);
1169  m_currentTxop->GotAck ();
1170  }
1171  NS_LOG_DEBUG ("rx not for me from=" << hdr.GetAddr2 ());
1172  }
1173  return;
1174 rxPacket:
1175  if (m_cfAckInfo.expectCfAck && hdr.IsCfAck ())
1176  {
1177  m_cfAckInfo.expectCfAck = false;
1178  NS_ASSERT (m_currentTxop != 0);
1179  m_currentTxop->GotAck ();
1180  }
1181  m_rxCallback (mpdu);
1182  return;
1183 }
1184 
1185 uint32_t
1187 {
1188  WifiMacHeader cfEnd;
1190  {
1191  cfEnd.SetType (WIFI_MAC_CTL_END_ACK);
1192  }
1193  else
1194  {
1195  cfEnd.SetType (WIFI_MAC_CTL_END);
1196  }
1197  return cfEnd.GetSize () + 4;
1198 }
1199 
1200 Time
1202 {
1203  WifiTxVector ackTxVector = GetAckTxVectorForData (to, dataTxVector.GetMode ());
1204  return GetAckDuration (ackTxVector);
1205 }
1206 
1207 Time
1209 {
1210  NS_ASSERT (ackTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
1211  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetFrequency ());
1212 }
1213 
1214 Time
1215 MacLow::GetBlockAckDuration (WifiTxVector blockAckReqTxVector, BlockAckType type) const
1216 {
1217  /*
1218  * For immediate Basic BlockAck we should transmit the frame with the same WifiMode
1219  * as the BlockAckReq.
1220  */
1221  return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, m_phy->GetFrequency ());
1222 }
1223 
1224 Time
1226 {
1227  return m_phy->CalculateTxDuration (GetBlockAckRequestSize (type), blockAckReqTxVector, m_phy->GetFrequency ());
1228 }
1229 
1230 Time
1232 {
1233  WifiTxVector ctsTxVector = GetCtsTxVectorForRts (to, rtsTxVector.GetMode ());
1234  return GetCtsDuration (ctsTxVector);
1235 }
1236 
1237 Time
1239 {
1240  NS_ASSERT (ctsTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1241  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetFrequency ());
1242 }
1243 
1246 {
1247  Mac48Address to = item->GetHeader ().GetAddr1 ();
1248  return m_stationManager->GetRtsTxVector (to, &item->GetHeader (), item->GetPacket ());
1249 }
1250 
1253 {
1254  Mac48Address to = item->GetHeader ().GetAddr1 ();
1255  return m_stationManager->GetDataTxVector (to, &item->GetHeader (), item->GetPacket ());
1256 }
1257 
1258 Time
1260  Mac48Address receiver) const
1261 {
1262  NS_LOG_FUNCTION (this << receiver << dataTxVector << params);
1263 
1264  Time duration = Seconds (0);
1265  if (params.MustWaitNormalAck ())
1266  {
1267  duration += GetSifs ();
1268  duration += GetAckDuration (receiver, dataTxVector);
1269  }
1270  else if (params.MustWaitBlockAck ())
1271  {
1272  duration += GetSifs ();
1273  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_self, dataTxVector.GetMode ());
1274  duration += GetBlockAckDuration (blockAckReqTxVector, params.GetBlockAckType ());
1275  }
1276  else if (params.MustSendBlockAckRequest ())
1277  {
1278  duration += 2 * GetSifs ();
1279  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_self, dataTxVector.GetMode ());
1280  duration += GetBlockAckRequestDuration (blockAckReqTxVector, params.GetBlockAckRequestType ());
1281  duration += GetBlockAckDuration (blockAckReqTxVector, params.GetBlockAckRequestType ());
1282  }
1283  return duration;
1284 }
1285 
1286 WifiMode
1288 {
1303  NS_LOG_FUNCTION (this << reqMode);
1305  bool found = false;
1306  //First, search the BSS Basic Rate set
1307  for (uint8_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
1308  {
1309  WifiMode testMode = m_stationManager->GetBasicMode (i);
1310  if ((!found || testMode.IsHigherDataRate (mode))
1311  && (!testMode.IsHigherDataRate (reqMode))
1313  {
1314  mode = testMode;
1315  //We've found a potentially-suitable transmit rate, but we
1316  //need to continue and consider all the basic rates before
1317  //we can be sure we've got the right one.
1318  found = true;
1319  }
1320  }
1322  {
1323  if (!found)
1324  {
1325  mode = m_stationManager->GetDefaultMcs ();
1326  for (uint8_t i = 0; i != m_stationManager->GetNBasicMcs (); i++)
1327  {
1328  WifiMode testMode = m_stationManager->GetBasicMcs (i);
1329  if ((!found || testMode.IsHigherDataRate (mode))
1330  && (!testMode.IsHigherDataRate (reqMode))
1331  && (testMode.GetModulationClass () == reqMode.GetModulationClass ()))
1332  {
1333  mode = testMode;
1334  //We've found a potentially-suitable transmit rate, but we
1335  //need to continue and consider all the basic rates before
1336  //we can be sure we've got the right one.
1337  found = true;
1338  }
1339  }
1340  }
1341  }
1342  //If we found a suitable rate in the BSSBasicRateSet, then we are
1343  //done and can return that mode.
1344  if (found)
1345  {
1346  NS_LOG_DEBUG ("MacLow::GetControlAnswerMode returning " << mode);
1347  return mode;
1348  }
1349 
1367  for (uint8_t idx = 0; idx < m_phy->GetNModes (); idx++)
1368  {
1369  WifiMode thismode = m_phy->GetMode (idx);
1370  /* If the rate:
1371  *
1372  * - is a mandatory rate for the PHY, and
1373  * - is equal to or faster than our current best choice, and
1374  * - is less than or equal to the rate of the received frame, and
1375  * - is of the same modulation class as the received frame
1376  *
1377  * ...then it's our best choice so far.
1378  */
1379  if (thismode.IsMandatory ()
1380  && (!found || thismode.IsHigherDataRate (mode))
1381  && (!thismode.IsHigherDataRate (reqMode))
1383  {
1384  mode = thismode;
1385  //As above; we've found a potentially-suitable transmit
1386  //rate, but we need to continue and consider all the
1387  //mandatory rates before we can be sure we've got the right one.
1388  found = true;
1389  }
1390  }
1392  {
1393  for (uint8_t idx = 0; idx < m_phy->GetNMcs (); idx++)
1394  {
1395  WifiMode thismode = m_phy->GetMcs (idx);
1396  if (thismode.IsMandatory ()
1397  && (!found || thismode.IsHigherDataRate (mode))
1398  && (!thismode.IsHigherCodeRate (reqMode))
1399  && (thismode.GetModulationClass () == reqMode.GetModulationClass ()))
1400  {
1401  mode = thismode;
1402  //As above; we've found a potentially-suitable transmit
1403  //rate, but we need to continue and consider all the
1404  //mandatory rates before we can be sure we've got the right one.
1405  found = true;
1406  }
1407  }
1408  }
1409 
1419  if (!found)
1420  {
1421  NS_FATAL_ERROR ("Can't find response rate for " << reqMode);
1422  }
1423 
1424  NS_LOG_DEBUG ("MacLow::GetControlAnswerMode returning " << mode);
1425  return mode;
1426 }
1427 
1430 {
1431  NS_ASSERT (!to.IsGroup ());
1432  WifiMode ctsMode = GetControlAnswerMode (rtsTxMode);
1433  WifiTxVector v;
1434  v.SetMode (ctsMode);
1438  uint16_t ctsTxGuardInterval = ConvertGuardIntervalToNanoSeconds (ctsMode, m_phy->GetShortGuardInterval (), m_phy->GetGuardInterval ());
1439  v.SetGuardInterval (ctsTxGuardInterval);
1440  v.SetNss (1);
1441  return v;
1442 }
1443 
1446 {
1447  NS_ASSERT (!to.IsGroup ());
1448  WifiMode ackMode = GetControlAnswerMode (dataTxMode);
1449  WifiTxVector v;
1450  v.SetMode (ackMode);
1454  uint16_t ackTxGuardInterval = ConvertGuardIntervalToNanoSeconds (ackMode, m_phy->GetShortGuardInterval (), m_phy->GetGuardInterval ());
1455  v.SetGuardInterval (ackTxGuardInterval);
1456  v.SetNss (1);
1457  return v;
1458 }
1459 
1462 {
1463  NS_ASSERT (!to.IsGroup ());
1464  WifiMode blockAckMode = GetControlAnswerMode (dataTxMode);
1465  WifiTxVector v;
1466  v.SetMode (blockAckMode);
1470 uint16_t blockAckTxGuardInterval = ConvertGuardIntervalToNanoSeconds (blockAckMode, m_phy->GetShortGuardInterval (), m_phy->GetGuardInterval ());
1471  v.SetGuardInterval (blockAckTxGuardInterval);
1472  v.SetNss (1);
1473  return v;
1474 }
1475 
1478 {
1479  return GetCtsTxVector (to, rtsTxMode);
1480 }
1481 
1484 {
1485  return GetAckTxVector (to, dataTxMode);
1486 }
1487 
1488 Time
1490  const WifiMacHeader* hdr,
1491  const MacLowTransmissionParameters& params,
1492  uint32_t fragmentSize) const
1493 {
1494  Ptr<const WifiMacQueueItem> item = Create<const WifiMacQueueItem> (packet, *hdr);
1495  Time txTime = CalculateOverheadTxTime (item, params);
1496  uint32_t dataSize;
1497  if (fragmentSize > 0)
1498  {
1499  Ptr<const Packet> fragment = Create<Packet> (fragmentSize);
1500  dataSize = GetSize (fragment, hdr, m_currentPacket && m_currentPacket->IsAggregate ());
1501  }
1502  else
1503  {
1504  dataSize = GetSize (packet, hdr, m_currentPacket && m_currentPacket->IsAggregate ());
1505  }
1506  txTime += m_phy->CalculateTxDuration (dataSize, GetDataTxVector (item), m_phy->GetFrequency ());
1507  return txTime;
1508 }
1509 
1510 Time
1512  const MacLowTransmissionParameters& params) const
1513 {
1514  Time txTime = Seconds (0);
1515  if (params.MustSendRts ())
1516  {
1517  WifiTxVector rtsTxVector = GetRtsTxVector (item);
1518  txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetFrequency ());
1519  txTime += GetCtsDuration (item->GetHeader ().GetAddr1 (), rtsTxVector);
1520  txTime += Time (GetSifs () * 2);
1521  }
1522  txTime += GetResponseDuration (params, GetDataTxVector (item), item->GetHeader ().GetAddr1 ());
1523 
1524  return txTime;
1525 }
1526 
1527 Time
1529  const WifiMacHeader* hdr,
1530  const MacLowTransmissionParameters& params) const
1531 {
1532  Time txTime = CalculateOverallTxTime (packet, hdr, params);
1533  if (params.HasNextPacket ())
1534  {
1535  WifiTxVector dataTxVector = GetDataTxVector (Create<const WifiMacQueueItem> (packet, *hdr));
1536  txTime += GetSifs ();
1537  txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, m_phy->GetFrequency ());
1538  }
1539  return txTime;
1540 }
1541 
1542 void
1544 {
1546  if (hdr.GetRawDuration () > 32767)
1547  {
1548  //All stations process Duration field values less than or equal to 32 767 from valid data frames
1549  //to update their NAV settings as appropriate under the coordination function rules.
1550  return;
1551  }
1552  if (hdr.IsCfEnd () && hdr.GetAddr2 () == m_bssid)
1553  {
1554  //see section 9.3.2.2 802.11-1999
1555  DoNavResetNow (Seconds (0));
1556  return;
1557  }
1558  else if (hdr.GetAddr1 () != m_self)
1559  {
1560  // see section 9.2.5.4 802.11-1999
1561  Time duration = hdr.GetDuration ();
1562  bool navUpdated = DoNavStartNow (duration);
1563  if (hdr.IsRts () && navUpdated)
1564  {
1573  WifiMacHeader cts;
1574  cts.SetType (WIFI_MAC_CTL_CTS);
1575  WifiTxVector txVector = GetRtsTxVector (Create<const WifiMacQueueItem> (packet, hdr));
1576  Time navCounterResetCtsMissedDelay =
1577  m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, m_phy->GetFrequency ()) +
1578  Time (2 * GetSifs ()) + Time (2 * GetSlotTime ());
1579  m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
1581  Simulator::Now ());
1582  }
1583  }
1584 }
1585 
1586 void
1588 {
1589  if (m_phy->GetLastRxStartTime () < rtsEndRxTime)
1590  {
1591  DoNavResetNow (Seconds (0));
1592  }
1593 }
1594 
1595 void
1597 {
1598  NS_LOG_FUNCTION (this << duration);
1599  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1600  {
1601  (*i)->NotifyNavResetNow (duration);
1602  }
1604  m_lastNavDuration = duration;
1605 }
1606 
1607 bool
1609 {
1610  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1611  {
1612  (*i)->NotifyNavStartNow (duration);
1613  }
1614  Time newNavEnd = Simulator::Now () + duration;
1615  Time oldNavEnd = m_lastNavStart + m_lastNavDuration;
1616  if (newNavEnd > oldNavEnd)
1617  {
1619  m_lastNavDuration = duration;
1620  return true;
1621  }
1622  return false;
1623 }
1624 
1625 void
1627 {
1628  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1629  {
1630  (*i)->NotifyAckTimeoutStartNow (duration);
1631  }
1632 }
1633 
1634 void
1636 {
1637  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1638  {
1639  (*i)->NotifyAckTimeoutResetNow ();
1640  }
1641 }
1642 
1643 void
1645 {
1646  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1647  {
1648  (*i)->NotifyCtsTimeoutStartNow (duration);
1649  }
1650 }
1651 
1652 void
1654 {
1655  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1656  {
1657  (*i)->NotifyCtsTimeoutResetNow ();
1658  }
1659 }
1660 
1661 void
1663 {
1664  NS_LOG_FUNCTION (this << psdu << txVector);
1665 
1666  NS_ASSERT (psdu->GetNMpdus ());
1667  const WifiMacHeader& hdr = (*psdu->begin ())->GetHeader ();
1668 
1669  NS_LOG_DEBUG ("send " << hdr.GetTypeString () <<
1670  ", to=" << hdr.GetAddr1 () <<
1671  ", size=" << psdu->GetSize () <<
1672  ", mode=" << txVector.GetMode () <<
1673  ", preamble=" << txVector.GetPreambleType () <<
1674  ", duration=" << hdr.GetDuration () <<
1675  ", seq=0x" << std::hex << hdr.GetSequenceControl () << std::dec);
1676 
1677  if (hdr.IsCfPoll () && m_stationManager->GetPcfSupported ())
1678  {
1679  Simulator::Schedule (GetPifs () + m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetFrequency ()), &MacLow::CfPollTimeout, this);
1680  }
1681  if (hdr.IsBeacon () && m_stationManager->GetPcfSupported ())
1682  {
1684  {
1686  }
1688  }
1689  else if (hdr.IsCfEnd () && m_stationManager->GetPcfSupported ())
1690  {
1691  m_cfpStart = NanoSeconds (0);
1693  m_cfAckInfo.appendCfAck = false;
1694  m_cfAckInfo.expectCfAck = false;
1695  }
1696  else if (IsCfPeriod () && hdr.HasData ())
1697  {
1698  m_cfAckInfo.expectCfAck = true;
1699  }
1700 
1701  if (psdu->IsSingle ())
1702  {
1703  txVector.SetAggregation (true);
1704  NS_LOG_DEBUG ("Sending S-MPDU");
1705  }
1706  else if (psdu->IsAggregate ())
1707  {
1708  txVector.SetAggregation (true);
1709  NS_LOG_DEBUG ("Sending A-MPDU");
1710  }
1711  else
1712  {
1713  NS_LOG_DEBUG ("Sending non aggregate MPDU");
1714  }
1715 
1716  for (auto& mpdu : *PeekPointer (psdu))
1717  {
1718  if (mpdu->GetHeader ().IsQosData ())
1719  {
1720  auto edcaIt = m_edca.find (QosUtilsMapTidToAc (mpdu->GetHeader ().GetQosTid ()));
1721  edcaIt->second->CompleteMpduTx (mpdu);
1722  }
1723  }
1724  m_phy->Send (psdu, txVector);
1725 }
1726 
1727 void
1729 {
1730  NS_LOG_FUNCTION (this);
1731  //to be reworked
1732  bool busy = false;
1733  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1734  {
1735  busy = (*i)->IsBusy ();
1736  }
1737  if (!busy)
1738  {
1739  NS_ASSERT (m_currentTxop != 0);
1741  m_cfAckInfo.expectCfAck = false;
1742  }
1743 }
1744 
1745 void
1747 {
1748  NS_LOG_FUNCTION (this);
1749  NS_LOG_DEBUG ("cts timeout");
1753  m_stationManager->ReportRtsFailed (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0));
1754 
1755  Ptr<QosTxop> qosTxop = DynamicCast<QosTxop> (m_currentTxop);
1756  if (qosTxop != 0)
1757  {
1759  }
1760  else
1761  {
1763  }
1764  m_currentTxop = 0;
1765 }
1766 
1767 void
1769 {
1770  NS_LOG_FUNCTION (this);
1771  NS_LOG_DEBUG ("normal ack timeout");
1775  Ptr<Txop> txop = m_currentTxop;
1776  m_currentTxop = 0;
1777  txop->MissedAck ();
1778 }
1779 
1780 void
1782 {
1783  NS_LOG_FUNCTION (this);
1784  NS_LOG_DEBUG ("block ack timeout");
1785  Ptr<Txop> txop = m_currentTxop;
1786  m_currentTxop = 0;
1787  txop->MissedBlockAck (m_currentPacket->GetNMpdus ());
1788 }
1789 
1790 void
1792 {
1793  NS_LOG_FUNCTION (this);
1794  /* send an RTS for this packet. */
1795  WifiMacHeader rts;
1796  rts.SetType (WIFI_MAC_CTL_RTS);
1797  rts.SetDsNotFrom ();
1798  rts.SetDsNotTo ();
1799  rts.SetNoRetry ();
1800  rts.SetNoMoreFragments ();
1801  rts.SetAddr1 (m_currentPacket->GetAddr1 ());
1802  rts.SetAddr2 (m_self);
1803  WifiTxVector rtsTxVector = GetRtsTxVector (*m_currentPacket->begin ());
1804  Time duration = Seconds (0);
1805 
1806  duration += GetSifs ();
1807  duration += GetCtsDuration (m_currentPacket->GetAddr1 (), rtsTxVector);
1808  duration += GetSifs ();
1809  duration += m_phy->CalculateTxDuration (m_currentPacket->GetSize (),
1811  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1812  if (m_txParams.HasNextPacket ())
1813  {
1816  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1817  }
1818  rts.SetDuration (duration);
1819 
1820  Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetFrequency ());
1821  Time timerDelay = txDuration + GetCtsTimeout ();
1822 
1824  NotifyCtsTimeoutStartNow (timerDelay);
1826 
1827  ForwardDown (Create<const WifiPsdu> (Create<Packet> (), rts), rtsTxVector);
1828 }
1829 
1830 void
1832 {
1833  Time txDuration = m_phy->CalculateTxDuration (m_currentPacket->GetSize (), dataTxVector, m_phy->GetFrequency ());
1834  if (m_txParams.MustWaitNormalAck () && !IsCfPeriod ())
1835  {
1836  Time timerDelay = txDuration + GetAckTimeout ();
1838  NotifyAckTimeoutStartNow (timerDelay);
1840  }
1842  {
1843  Time timerDelay = txDuration + GetBasicBlockAckTimeout ();
1845  NotifyAckTimeoutStartNow (timerDelay);
1847  }
1848  else if (m_txParams.MustWaitBlockAck () &&
1851  {
1852  Time timerDelay = txDuration + GetCompressedBlockAckTimeout ();
1854  NotifyAckTimeoutStartNow (timerDelay);
1856  }
1857  else if (m_txParams.HasNextPacket ())
1858  {
1860  Time delay = txDuration;
1862  {
1863  delay += GetRifs ();
1864  }
1865  else
1866  {
1867  delay += GetSifs ();
1868  }
1870  }
1871  else if (m_currentPacket->GetHeader (0).IsQosData () && m_currentTxop->IsQosTxop () &&
1873  {
1874  Time delay = txDuration;
1876  {
1877  delay += GetRifs ();
1878  }
1879  else
1880  {
1881  delay += GetSifs ();
1882  }
1884  }
1885  else
1886  {
1887  // since we do not expect any timer to be triggered.
1889  }
1890 }
1891 
1892 void
1894 {
1895  NS_LOG_FUNCTION (this);
1896  /* send this packet directly. No RTS is needed. */
1898 
1899  if (!IsCfPeriod ())
1900  {
1902  if (m_txParams.HasNextPacket ())
1903  {
1905  {
1906  duration += GetRifs ();
1907  }
1908  else
1909  {
1910  duration += GetSifs ();
1911  }
1914  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1915  }
1916  m_currentPacket->SetDuration (duration);
1917  }
1918  else
1919  {
1920  if (m_currentPacket->GetHeader (0).IsCfEnd ())
1921  {
1922  m_currentPacket->GetHeader (0).SetRawDuration (0);
1923  }
1924  else
1925  {
1926  m_currentPacket->GetHeader (0).SetRawDuration (32768);
1927  }
1928  }
1929 
1930  if (!m_currentPacket->IsAggregate ())
1931  {
1933  {
1934  switch (m_currentPacket->GetHeader (0).GetType ())
1935  {
1936  case WIFI_MAC_DATA:
1937  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_CFACK, false);
1938  break;
1939  case WIFI_MAC_DATA_CFPOLL:
1940  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_CFACK_CFPOLL, false);
1941  break;
1942  case WIFI_MAC_DATA_NULL:
1943  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_NULL_CFACK, false);
1944  break;
1946  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_NULL_CFACK_CFPOLL, false);
1947  break;
1948  case WIFI_MAC_CTL_END:
1949  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_CTL_END_ACK, false);
1950  break;
1951  default:
1952  NS_ASSERT (false);
1953  break;
1954  }
1956  //Standard says that, for frames of type Data+CF-ACK, Data+CF-Poll+CF-ACK, and CF-Poll+CF-ACK,
1957  //the rate chosen to transmit the frame must be supported by both the addressed recipient STA and the STA to which the ACK is intended.
1958  //This ideally requires the rate manager to handle this case, but this requires to update all rate manager classes.
1959  //Instead, we simply fetch two TxVector and we select the one with the lowest datarate.
1960  //This should be later changed, at the latest once HCCA is implemented for HT/VHT/HE stations.
1961  WifiMacHeader tmpHdr = m_currentPacket->GetHeader (0);
1962  tmpHdr.SetAddr1 (m_cfAckInfo.address);
1963  WifiTxVector tmpTxVector = GetDataTxVector (Create<const WifiMacQueueItem> (m_currentPacket->GetPayload (0), tmpHdr));
1964  if (tmpTxVector.GetMode ().GetDataRate (tmpTxVector) < m_currentTxVector.GetMode ().GetDataRate (m_currentTxVector))
1965  {
1966  m_currentTxVector = tmpTxVector;
1967  }
1968  m_cfAckInfo.appendCfAck = false;
1970  }
1971  }
1973  {
1974  Ptr<QosTxop> qosTxop = DynamicCast<QosTxop> (m_currentTxop);
1975  NS_ASSERT (qosTxop != 0);
1976  auto bar = qosTxop->PrepareBlockAckRequest (m_currentPacket->GetAddr1 (), *m_currentPacket->GetTids ().begin ());
1977  qosTxop->ScheduleBar (bar);
1978  }
1980 }
1981 
1982 bool
1983 MacLow::IsNavZero (void) const
1984 {
1986 }
1987 
1988 void
1990 {
1991  WifiMacHeader cts;
1992  cts.SetType (WIFI_MAC_CTL_CTS);
1993  cts.SetDsNotFrom ();
1994  cts.SetDsNotTo ();
1995  cts.SetNoMoreFragments ();
1996  cts.SetNoRetry ();
1997  cts.SetAddr1 (m_self);
1998 
1999  WifiTxVector ctsTxVector = GetRtsTxVector (*m_currentPacket->begin ());
2000  Time duration = Seconds (0);
2001 
2002  duration += GetSifs ();
2003  duration += m_phy->CalculateTxDuration (m_currentPacket->GetSize (),
2005  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
2006  if (m_txParams.HasNextPacket ())
2007  {
2008  duration += GetSifs ();
2011  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
2012  }
2013 
2014  cts.SetDuration (duration);
2015 
2016  ForwardDown (Create<const WifiPsdu> (Create<Packet> (), cts), ctsTxVector);
2017 
2018  Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetFrequency ());
2019  txDuration += GetSifs ();
2021 
2022  m_sendDataEvent = Simulator::Schedule (txDuration,
2023  &MacLow::SendDataAfterCts, this,
2024  duration);
2025 }
2026 
2027 void
2028 MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
2029 {
2030  NS_LOG_FUNCTION (this << source << duration << rtsTxVector.GetMode () << rtsSnr);
2031  /* send a CTS when you receive a RTS
2032  * right after SIFS.
2033  */
2034  WifiTxVector ctsTxVector = GetCtsTxVector (source, rtsTxVector.GetMode ());
2035  WifiMacHeader cts;
2036  cts.SetType (WIFI_MAC_CTL_CTS);
2037  cts.SetDsNotFrom ();
2038  cts.SetDsNotTo ();
2039  cts.SetNoMoreFragments ();
2040  cts.SetNoRetry ();
2041  cts.SetAddr1 (source);
2042  duration -= GetCtsDuration (source, rtsTxVector);
2043  duration -= GetSifs ();
2044  NS_ASSERT (duration.IsPositive ());
2045  cts.SetDuration (duration);
2046 
2047  Ptr<Packet> packet = Create<Packet> ();
2048 
2049  SnrTag tag;
2050  tag.Set (rtsSnr);
2051  packet->AddPacketTag (tag);
2052 
2053  //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
2054  ForwardDown (Create<const WifiPsdu> (packet, cts), ctsTxVector);
2055 }
2056 
2057 void
2059 {
2060  NS_LOG_FUNCTION (this);
2061  /* send the third step in a
2062  * RTS/CTS/DATA/ACK handshake
2063  */
2064  NS_ASSERT (m_currentPacket != 0);
2065 
2067  Time newDuration = GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
2068  if (m_txParams.HasNextPacket ())
2069  {
2071  {
2072  newDuration += GetRifs ();
2073  }
2074  else
2075  {
2076  newDuration += GetSifs ();
2077  }
2079  newDuration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
2080  }
2081 
2083  duration -= txDuration;
2084  duration -= GetSifs ();
2085 
2086  duration = std::max (duration, newDuration);
2087  NS_ASSERT (duration.IsPositive ());
2088  m_currentPacket->SetDuration (duration);
2090  {
2091  Ptr<QosTxop> qosTxop = DynamicCast<QosTxop> (m_currentTxop);
2092  NS_ASSERT (qosTxop != 0);
2093  auto bar = qosTxop->PrepareBlockAckRequest (m_currentPacket->GetAddr1 (), *m_currentPacket->GetTids ().begin ());
2094  qosTxop->ScheduleBar (bar);
2095  }
2097 }
2098 
2099 void
2101 {
2102  NS_LOG_FUNCTION (this);
2104 }
2105 
2106 void
2108 {
2109  NS_LOG_FUNCTION (this);
2111 }
2112 
2113 void
2115 {
2116  NS_LOG_FUNCTION (this);
2117  if (m_currentPacket->GetHeader (0).IsBeacon () && m_stationManager->GetPcfSupported ())
2118  {
2120  }
2121  if (!m_cfAckInfo.expectCfAck)
2122  {
2123  Ptr<Txop> txop = m_currentTxop;
2124  txop->EndTxNoAck ();
2125  }
2126  if (!IsCfPeriod ())
2127  {
2128  m_currentTxop = 0;
2129  }
2130 }
2131 
2132 void
2133 MacLow::SendAckAfterData (Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
2134 {
2135  NS_LOG_FUNCTION (this);
2136  // send an ACK, after SIFS, when you receive a packet
2137  WifiTxVector ackTxVector = GetAckTxVector (source, dataTxMode);
2138  WifiMacHeader ack;
2139  ack.SetType (WIFI_MAC_CTL_ACK);
2140  ack.SetDsNotFrom ();
2141  ack.SetDsNotTo ();
2142  ack.SetNoRetry ();
2143  ack.SetNoMoreFragments ();
2144  ack.SetAddr1 (source);
2145  // 802.11-2012, Section 8.3.1.4: Duration/ID is received duration value
2146  // minus the time to transmit the ACK frame and its SIFS interval
2147  duration -= GetAckDuration (ackTxVector);
2148  duration -= GetSifs ();
2149  NS_ASSERT_MSG (duration.IsPositive (), "Please provide test case to maintainers if this assert is hit.");
2150  ack.SetDuration (duration);
2151 
2152  Ptr<Packet> packet = Create<Packet> ();
2153 
2154  SnrTag tag;
2155  tag.Set (dataSnr);
2156  packet->AddPacketTag (tag);
2157 
2158  //ACK should always use non-HT PPDU (HT PPDU cases not supported yet)
2159  ForwardDown (Create<const WifiPsdu> (packet, ack), ackTxVector);
2160 }
2161 
2162 bool
2164 {
2165  const WifiMacHeader& hdr = mpdu->GetHeader ();
2166 
2170  {
2171  Mac48Address originator = hdr.GetAddr2 ();
2172  uint8_t tid = 0;
2173  if (hdr.IsQosData ())
2174  {
2175  tid = hdr.GetQosTid ();
2176  }
2177  uint16_t seqNumber = hdr.GetSequenceNumber ();
2178  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2179  if (it != m_bAckAgreements.end ())
2180  {
2181  //Implement HT immediate Block Ack support for HT Delayed Block Ack is not added yet
2182  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), seqNumber))
2183  {
2184  StoreMpduIfNeeded (mpdu);
2185  if (!IsInWindow (hdr.GetSequenceNumber (), (*it).second.first.GetStartingSequence (), (*it).second.first.GetBufferSize ()))
2186  {
2187  uint16_t delta = (seqNumber - (*it).second.first.GetWinEnd () + 4096) % 4096;
2188  NS_ASSERT (delta > 0);
2189  uint16_t bufferSize = (*it).second.first.GetBufferSize ();
2190  uint16_t startingSeq = (seqNumber - bufferSize + 1 + 4096) % 4096;
2191  (*it).second.first.SetStartingSequence (startingSeq);
2192  RxCompleteBufferedPacketsWithSmallerSequence ((*it).second.first.GetStartingSequenceControl (), originator, tid);
2193  }
2194  RxCompleteBufferedPacketsUntilFirstLost (originator, tid); //forwards up packets starting from winstart and set winstart to last +1
2195  }
2196  return true;
2197  }
2198  return false;
2199  }
2200  return StoreMpduIfNeeded (mpdu);
2201 }
2202 
2203 bool
2205 {
2206  const WifiMacHeader& hdr = mpdu->GetHeader ();
2207 
2208  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2209  if (it != m_bAckAgreements.end ())
2210  {
2211  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2212  uint32_t mappedSeqControl = QosUtilsMapSeqControlToUniqueInteger (hdr.GetSequenceControl (), endSequence);
2213 
2214  BufferedPacketI i = (*it).second.second.begin ();
2215  for (; i != (*it).second.second.end ()
2216  && QosUtilsMapSeqControlToUniqueInteger ((*i)->GetHeader ().GetSequenceControl (), endSequence) < mappedSeqControl; i++)
2217  {
2218  }
2219  (*it).second.second.insert (i, mpdu);
2220 
2221  //Update block ack cache
2222  BlockAckCachesI j = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2223  NS_ASSERT (j != m_bAckCaches.end ());
2224  (*j).second.UpdateWithMpdu (&hdr);
2225  return true;
2226  }
2227  return false;
2228 }
2229 
2230 void
2232  uint16_t startingSeq)
2233 {
2234  NS_LOG_FUNCTION (this);
2235  uint8_t tid = respHdr->GetTid ();
2236  BlockAckAgreement agreement (originator, tid);
2237  if (respHdr->IsImmediateBlockAck ())
2238  {
2239  agreement.SetImmediateBlockAck ();
2240  }
2241  else
2242  {
2243  agreement.SetDelayedBlockAck ();
2244  }
2245  agreement.SetAmsduSupport (respHdr->IsAmsduSupported ());
2246  agreement.SetBufferSize (respHdr->GetBufferSize () + 1);
2247  agreement.SetTimeout (respHdr->GetTimeout ());
2248  agreement.SetStartingSequence (startingSeq);
2249 
2250  std::list<Ptr<WifiMacQueueItem>> buffer (0);
2251  AgreementKey key (originator, respHdr->GetTid ());
2252  AgreementValue value (agreement, buffer);
2253  m_bAckAgreements.insert (std::make_pair (key, value));
2254 
2255  BlockAckCache cache;
2256  cache.Init (startingSeq, respHdr->GetBufferSize () + 1);
2257  m_bAckCaches.insert (std::make_pair (key, cache));
2258 
2259  if (respHdr->GetTimeout () != 0)
2260  {
2261  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, respHdr->GetTid ()));
2262  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2263 
2264  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2265 
2266  it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
2268  m_edca[ac], originator, tid, false);
2269  }
2270 }
2271 
2272 void
2274 {
2275  NS_LOG_FUNCTION (this);
2276  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2277  if (it != m_bAckAgreements.end ())
2278  {
2279  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (), originator, tid);
2280  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2281  m_bAckAgreements.erase (it);
2282  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2283  NS_ASSERT (i != m_bAckCaches.end ());
2284  m_bAckCaches.erase (i);
2285  }
2286 }
2287 
2288 void
2290 {
2291  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2292  if (it != m_bAckAgreements.end ())
2293  {
2294  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2295  uint32_t mappedStart = QosUtilsMapSeqControlToUniqueInteger (seq, endSequence);
2296  BufferedPacketI last = (*it).second.second.begin ();
2297  uint16_t guard = 0;
2298  if (last != (*it).second.second.end ())
2299  {
2300  guard = (*(*it).second.second.begin ())->GetHeader ().GetSequenceControl ();
2301  }
2302  BufferedPacketI i = (*it).second.second.begin ();
2303  for (; i != (*it).second.second.end ()
2304  && QosUtilsMapSeqControlToUniqueInteger ((*i)->GetHeader ().GetSequenceControl (), endSequence) < mappedStart; )
2305  {
2306  if (guard == (*i)->GetHeader ().GetSequenceControl ())
2307  {
2308  if (!(*i)->GetHeader ().IsMoreFragments ())
2309  {
2310  while (last != i)
2311  {
2312  m_rxCallback (*last);
2313  last++;
2314  }
2315  m_rxCallback (*last);
2316  last++;
2317  /* go to next packet */
2318  while (i != (*it).second.second.end () && guard == (*i)->GetHeader ().GetSequenceControl ())
2319  {
2320  i++;
2321  }
2322  if (i != (*it).second.second.end ())
2323  {
2324  guard = (*i)->GetHeader ().GetSequenceControl ();
2325  last = i;
2326  }
2327  }
2328  else
2329  {
2330  guard++;
2331  }
2332  }
2333  else
2334  {
2335  /* go to next packet */
2336  while (i != (*it).second.second.end () && guard == (*i)->GetHeader ().GetSequenceControl ())
2337  {
2338  i++;
2339  }
2340  if (i != (*it).second.second.end ())
2341  {
2342  guard = (*i)->GetHeader ().GetSequenceControl ();
2343  last = i;
2344  }
2345  }
2346  }
2347  (*it).second.second.erase ((*it).second.second.begin (), i);
2348  }
2349 }
2350 
2351 void
2353 {
2354  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2355  if (it != m_bAckAgreements.end ())
2356  {
2357  uint16_t guard = (*it).second.first.GetStartingSequenceControl ();
2358  BufferedPacketI lastComplete = (*it).second.second.begin ();
2359  BufferedPacketI i = (*it).second.second.begin ();
2360  for (; i != (*it).second.second.end () && guard == (*i)->GetHeader ().GetSequenceControl (); i++)
2361  {
2362  if (!(*i)->GetHeader ().IsMoreFragments ())
2363  {
2364  while (lastComplete != i)
2365  {
2366  m_rxCallback (*lastComplete);
2367  lastComplete++;
2368  }
2369  m_rxCallback (*lastComplete);
2370  lastComplete++;
2371  }
2372  guard = (*i)->GetHeader ().IsMoreFragments () ? (guard + 1) : ((guard + 16) & 0xfff0);
2373  }
2374  (*it).second.first.SetStartingSequenceControl (guard);
2375  /* All packets already forwarded to WifiMac must be removed from buffer:
2376  [begin (), lastComplete) */
2377  (*it).second.second.erase ((*it).second.second.begin (), lastComplete);
2378  }
2379 }
2380 
2381 void
2382 MacLow::SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate,
2383  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2384 {
2385  NS_LOG_FUNCTION (this);
2386  Ptr<Packet> packet = Create<Packet> ();
2387  packet->AddHeader (*blockAck);
2388 
2389  WifiMacHeader hdr;
2391  hdr.SetAddr1 (originator);
2392  hdr.SetAddr2 (GetAddress ());
2393  hdr.SetDsNotFrom ();
2394  hdr.SetDsNotTo ();
2395  hdr.SetNoRetry ();
2396  hdr.SetNoMoreFragments ();
2397 
2398  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (originator, blockAckReqTxMode);
2399 
2400  if (immediate)
2401  {
2403  duration -= GetSifs ();
2404  duration -= GetBlockAckDuration (blockAckReqTxVector, blockAck->GetType ());
2405  }
2406  else
2407  {
2408  m_txParams.EnableAck ();
2409  duration += GetSifs ();
2410  duration += GetAckDuration (originator, blockAckReqTxVector);
2411  }
2413 
2414  if (!immediate)
2415  {
2416  StartDataTxTimers (blockAckReqTxVector);
2417  }
2418 
2419  NS_ASSERT (duration.IsPositive ());
2420  hdr.SetDuration (duration);
2421  //here should be present a control about immediate or delayed block ack
2422  //for now we assume immediate
2423  SnrTag tag;
2424  tag.Set (rxSnr);
2425  packet->AddPacketTag (tag);
2426  ForwardDown (Create<const WifiPsdu> (packet, hdr), blockAckReqTxVector);
2427 }
2428 
2429 void
2430 MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector, double rxSnr)
2431 {
2432  NS_LOG_FUNCTION (this);
2433  if (!m_phy->IsStateTx () && !m_phy->IsStateRx ())
2434  {
2435  NS_LOG_FUNCTION (this << +tid << originator << duration.As (Time::S) << blockAckReqTxVector << rxSnr);
2436  CtrlBAckResponseHeader blockAck;
2437  uint16_t seqNumber = 0;
2438  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2439  NS_ASSERT (i != m_bAckCaches.end ());
2440  seqNumber = (*i).second.GetWinStart ();
2441 
2442  bool immediate = true;
2443  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2444  blockAck.SetStartingSequence (seqNumber);
2445  blockAck.SetTidInfo (tid);
2446  immediate = (*it).second.first.IsImmediateBlockAck ();
2447  if ((*it).second.first.GetBufferSize () > 64)
2448  {
2449  blockAck.SetType (EXTENDED_COMPRESSED_BLOCK_ACK);
2450  }
2451  else
2452  {
2453  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2454  }
2455  NS_LOG_DEBUG ("Got Implicit block Ack Req with seq " << seqNumber);
2456  (*i).second.FillBlockAckBitmap (&blockAck);
2457 
2458  WifiTxVector blockAckTxVector = GetBlockAckTxVector (originator, blockAckReqTxVector.GetMode ());
2459 
2460  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckTxVector.GetMode (), rxSnr);
2461  }
2462  else
2463  {
2464  NS_LOG_DEBUG ("Skip block ack response!");
2465  }
2466 }
2467 
2468 void
2470  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2471 {
2472  NS_LOG_FUNCTION (this);
2473  CtrlBAckResponseHeader blockAck;
2474  uint8_t tid = 0;
2475  bool immediate = false;
2476  if (!reqHdr.IsMultiTid ())
2477  {
2478  tid = reqHdr.GetTidInfo ();
2479  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2480  if (it != m_bAckAgreements.end ())
2481  {
2482  blockAck.SetStartingSequence (reqHdr.GetStartingSequence ());
2483  blockAck.SetTidInfo (tid);
2484  immediate = (*it).second.first.IsImmediateBlockAck ();
2485  if (reqHdr.IsBasic ())
2486  {
2487  blockAck.SetType (BASIC_BLOCK_ACK);
2488  }
2489  else if (reqHdr.IsCompressed ())
2490  {
2491  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2492  }
2493  else if (reqHdr.IsExtendedCompressed ())
2494  {
2496  }
2497  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2498  NS_ASSERT (i != m_bAckCaches.end ());
2499  (*i).second.FillBlockAckBitmap (&blockAck);
2500  NS_LOG_DEBUG ("Got block Ack Req with seq " << reqHdr.GetStartingSequence ());
2501 
2505  {
2506  /* All packets with smaller sequence than starting sequence control must be passed up to Wifimac
2507  * See 9.10.3 in IEEE 802.11e standard.
2508  */
2510  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2511  }
2512  else
2513  {
2514  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), reqHdr.GetStartingSequence ()))
2515  {
2516  (*it).second.first.SetStartingSequence (reqHdr.GetStartingSequence ());
2518  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2519  }
2520  }
2521  }
2522  else
2523  {
2524  NS_LOG_DEBUG ("there's not a valid block ack agreement with " << originator);
2525  }
2526  }
2527  else
2528  {
2529  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2530  }
2531  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode, rxSnr);
2532 }
2533 
2534 void
2536 {
2537  if (agreement.GetTimeout () != 0)
2538  {
2539  NS_ASSERT (agreement.m_inactivityEvent.IsRunning ());
2540  agreement.m_inactivityEvent.Cancel ();
2541  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2542  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2545  m_edca[ac], agreement.GetPeer (),
2546  agreement.GetTid (), false);
2547  }
2548 }
2549 
2550 void
2552 {
2553  m_edca.insert (std::make_pair (ac, edca));
2554 }
2555 
2556 void
2557 MacLow::DeaggregateAmpduAndReceive (Ptr<WifiPsdu> psdu, double rxSnr, WifiTxVector txVector, std::vector<bool> statusPerMpdu)
2558 {
2559  NS_LOG_FUNCTION (this);
2560  bool normalAck = false;
2561  bool ampduSubframe = false; //flag indicating the packet belongs to an A-MPDU and is not a VHT/HE single MPDU
2562  if (txVector.IsAggregation ())
2563  {
2564  NS_ASSERT (psdu->IsAggregate ());
2565  ampduSubframe = true;
2566  auto n = psdu->begin ();
2567  auto status = statusPerMpdu.begin ();
2568  NS_ABORT_MSG_IF (psdu->GetNMpdus () != statusPerMpdu.size (), "Should have one receive status per MPDU");
2569 
2570  WifiMacHeader firsthdr = (*n)->GetHeader ();
2571  NS_LOG_DEBUG ("duration/id=" << firsthdr.GetDuration ());
2572  NotifyNav ((*n)->GetPacket (), firsthdr);
2573 
2574  if (firsthdr.GetAddr1 () == m_self)
2575  {
2576  //Iterate over all MPDUs and notify reception only if status OK
2577  for (; n != psdu->end (); ++n, ++status)
2578  {
2579  firsthdr = (*n)->GetHeader ();
2580  NS_ABORT_MSG_IF (firsthdr.GetAddr1 () != m_self, "All MPDUs of A-MPDU should have the same destination address");
2581  if (*status) //PER and thus CRC check succeeded
2582  {
2583  if (psdu->IsSingle ())
2584  {
2585  //If the MPDU is sent as a VHT/HE single MPDU (EOF=1 in A-MPDU subframe header), then the responder sends an ACK.
2586  NS_LOG_DEBUG ("Receive S-MPDU");
2587  ampduSubframe = false;
2588  }
2589  else if (!m_sendAckEvent.IsRunning () && firsthdr.IsQosAck ()) // Implicit BAR Ack Policy
2590  {
2593  firsthdr.GetQosTid (),
2594  firsthdr.GetAddr2 (),
2595  firsthdr.GetDuration (),
2596  txVector, rxSnr);
2597  }
2598 
2599  if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ())
2600  {
2601  ReceiveOk ((*n), rxSnr, txVector, ampduSubframe);
2602  }
2603  else if (firsthdr.IsData () || firsthdr.IsQosData ())
2604  {
2605  NS_LOG_DEBUG ("Deaggregate packet from " << firsthdr.GetAddr2 () << " with sequence=" << firsthdr.GetSequenceNumber ());
2606  ReceiveOk ((*n), rxSnr, txVector, ampduSubframe);
2607  if (firsthdr.IsQosAck ())
2608  {
2609  NS_LOG_DEBUG ("Normal Ack");
2610  normalAck = true;
2611  }
2612  }
2613  else
2614  {
2615  NS_FATAL_ERROR ("Received A-MPDU with invalid first MPDU type");
2616  }
2617 
2618  if (!psdu->IsSingle ())
2619  {
2620  if (normalAck)
2621  {
2622  //send block Ack
2623  if (firsthdr.IsBlockAckReq ())
2624  {
2625  NS_FATAL_ERROR ("Sending a BlockAckReq with QosPolicy equal to Normal Ack");
2626  }
2627  uint8_t tid = firsthdr.GetQosTid ();
2628  AgreementsI it = m_bAckAgreements.find (std::make_pair (firsthdr.GetAddr2 (), tid));
2629  if (it != m_bAckAgreements.end ())
2630  {
2631  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
2632  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
2633  NS_LOG_DEBUG ("rx A-MPDU/sendImmediateBlockAck from=" << firsthdr.GetAddr2 ());
2635  }
2636  else
2637  {
2638  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
2639  }
2640  }
2641  }
2642  }
2643  }
2644  }
2645  }
2646  else
2647  {
2648  /* Simple MPDU */
2649  NS_ASSERT (!psdu->IsAggregate ());
2650  ReceiveOk ((*psdu->begin ()), rxSnr, txVector, ampduSubframe);
2651  }
2652 }
2653 
2654 Time
2656 {
2657  NS_LOG_FUNCTION (this);
2659  NS_ASSERT (remainingCfpDuration.IsPositive ());
2660  return remainingCfpDuration;
2661 }
2662 
2663 bool
2665 {
2667 }
2668 
2669 bool
2671 {
2672  NS_LOG_FUNCTION (this);
2673  if (!IsCfPeriod ())
2674  {
2675  return false;
2676  }
2677  NS_ASSERT (GetRemainingCfpDuration ().IsPositive ());
2678  WifiMacHeader hdr;
2679  hdr.SetType (WIFI_MAC_DATA);
2680  WifiMacTrailer fcs;
2681  uint32_t maxMacFrameSize = MAX_MSDU_SIZE + hdr.GetSerializedSize () + fcs.GetSerializedSize ();
2683  return ((GetRemainingCfpDuration () - nextTransmission).IsPositive ());
2684 }
2685 
2686 } //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:2107
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 GetRifs(void) const
Return Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:444
void ScheduleBar(Ptr< const WifiMacQueueItem > bar, bool skipIfNoDataQueued=false)
Definition: qos-txop.cc:167
bool IsCfEnd(void) const
Return true if the header is a CF-END header.
void SetPifs(Time pifs)
Set PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:372
Time m_ctsTimeout
CTS timeout duration.
Definition: mac-low.h:944
bool IsStateOff(void) const
Definition: wifi-phy.cc:4004
Ptr< const WifiMacQueueItem > PeekNextFrame(uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast())
Peek the next frame to transmit to the given receiver and of the given TID from the Block Ack manager...
Definition: qos-txop.cc:253
bool GetRifsPermitted(void) const
Return whether the device can use RIFS.
bool IsAggregation(void) const
Checks whether the PSDU contains A-MPDU.
uint16_t GetTimeout(void) const
Return the timeout.
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:934
bool GetVhtSupported(void) const
Return whether the device has VHT capability support enabled.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
std::vector< Ptr< ChannelAccessManager > >::const_iterator ChannelAccessManagersCI
typedef for an iterator for a list of ChannelAccessManager.
Definition: mac-low.h:916
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:2535
EventId m_blockAckTimeoutEvent
Block ACK timeout event.
Definition: mac-low.h:927
Time CalculateOverallTxTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &params, uint32_t fragmentSize=0) const
Definition: mac-low.cc:1489
Callback template class.
Definition: callback.h:1273
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
Ptr< MpduAggregator > GetMpduAggregator(void) const
Returns the aggregator used to construct A-MPDU subframes.
Definition: mac-low.cc:298
WifiMode GetMcs(uint8_t mcs) const
The WifiPhy::GetMcs() method is used (e.g., by a WifiRemoteStationManager) to determine the set of tr...
Definition: wifi-phy.cc:3932
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:2469
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
bool ReceiveMpdu(Ptr< WifiMacQueueItem > mpdu)
Definition: mac-low.cc:2163
void SetDuration(Time duration)
Set the Duration/ID field with the given duration (Time object).
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
static Time Min()
Minimum representable Time.
Definition: nstime.h:268
void SetPromisc(void)
Enable promiscuous mode.
Definition: mac-low.cc:402
bool IsCtl(void) const
Return true if the Type is Control.
#define min(a, b)
Definition: 80211b.c:42
virtual void StartNextPacket(void)
Start transmission for the next packet if allowed by the TxopLimit.
Definition: txop.cc:871
void DoNavResetNow(Time duration)
Reset NAV with the given duration.
Definition: mac-low.cc:1596
bool GetShortGuardInterval(void) const
Return whether short guard interval is supported.
Definition: wifi-phy.cc:664
Ptr< Txop > m_currentTxop
Current TXOP.
Definition: mac-low.h:937
virtual void EndTxNoAck(void)
Event handler when a transmission that does not require an ACK has completed.
Definition: txop.cc:771
void NotifyMaybeCcaBusyStart(Time duration)
Definition: mac-low.cc:84
void SetupPhyMacLowListener(const Ptr< WifiPhy > phy)
Set up WifiPhy listener for this MacLow.
Definition: mac-low.cc:155
virtual void StartNextFragment(void)
Start transmission for the next fragment.
Definition: txop.cc:742
uint32_t GetRtsSize(void)
Return the total RTS size (including FCS trailer).
Definition: wifi-utils.cc:209
Ptr< QosTxop > GetEdca(uint8_t tid) const
Definition: mac-low.cc:272
Ptr< MsduAggregator > m_msduAggregator
A-MSDU aggregator.
Definition: mac-low.h:923
Time m_pifs
PCF Interframe Space (PIFS) duration.
Definition: mac-low.h:947
void SetPhy(const Ptr< WifiPhy > phy)
Set up WifiPhy associated with this MacLow.
Definition: mac-low.cc:248
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:238
bool DoNavStartNow(Time duration)
Start NAV with the given duration.
Definition: mac-low.cc:1608
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
void SetSifs(Time sifs)
Set Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:360
void NotifySwitchingStart(Time duration)
Definition: mac-low.cc:87
void ReportDataOk(Mac48Address address, const WifiMacHeader *header, double ackSnr, WifiMode ackMode, double dataSnr, uint32_t packetSize)
Should be invoked whenever we receive the Ack associated to a data packet we just sent...
std::pair< Mac48Address, uint8_t > AgreementKey
agreement key typedef
Definition: mac-low.h:969
void SetNoMoreFragments(void)
Un-set the More Fragment bit in the Frame Control Field.
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:460
virtual void MissedAck(void)
Event handler when an ACK is missed.
Definition: txop.cc:670
Time CalculateOverheadTxTime(Ptr< const WifiMacQueueItem > item, const MacLowTransmissionParameters &params) const
Definition: mac-low.cc:1511
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
bool GetHeSupported(void) const
Return whether the device has HE capability support enabled.
#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 ReceiveError(Ptr< WifiPsdu > psdu)
Definition: mac-low.cc:719
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:566
void Init(uint16_t winStart, uint16_t winSize)
Init function.
Time GetResponseDuration(const MacLowTransmissionParameters &params, WifiTxVector dataTxVector, Mac48Address receiver) const
Return the time required to transmit the response frames (ACK or BAR+BA following the policy configur...
Definition: mac-low.cc:1259
WifiMode GetDefaultMcs(void) const
Return the default Modulation and Coding Scheme (MCS) index.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
bool IsNavZero(void) const
Check if NAV is zero.
Definition: mac-low.cc:1983
void NotifyOffNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:771
void NotifySleepNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:756
void NotifyNav(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Notify NAV function.
Definition: mac-low.cc:1543
WifiMode GetBasicMcs(uint8_t i) const
Return the MCS at the given list index.
Mac48Address GetBssid(void) const
Return the Basic Service Set Identification.
Definition: mac-low.cc:462
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...
Definition: qos-txop.cc:1648
Ptr< WifiAckPolicySelector > GetAckPolicySelector(void) const
Return the ack policy selector.
Definition: qos-txop.cc:188
#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:84
bool IsStrictlyPositive(void) const
Definition: nstime.h:308
virtual void Cancel(void)
Cancel the transmission.
Definition: txop.cc:764
uint32_t GetAckSize(void)
Return the total ACK size (including FCS trailer).
Definition: wifi-utils.cc:181
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:745
uint16_t GetBufferSize(void) const
Return the buffer size.
Callback< R > MakeNullCallback(void)
Definition: callback.h:1786
VHT PHY (Clause 22)
Definition: wifi-mode.h:60
TimeWithUnit As(const enum Unit unit) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:389
WifiTxVector GetRtsTxVector(Ptr< const WifiMacQueueItem > item) const
Return a TXVECTOR for the RTS frame given the destination.
Definition: mac-low.cc:1245
Mac48Address m_bssid
BSSID address (Mac48Address)
Definition: mac-low.h:940
ns3::Time timeout
WifiPreamble GetPreambleForTransmission(WifiModulationClass modulation, bool useShortPreamble, bool useGreenfield)
Return the preamble to be used for the transmission.
Definition: wifi-utils.cc:128
const char * GetTypeString(void) const
Return a string corresponds to the header type.
bool IsCfPoll(void) const
Return true if the Type/Subtype is one of the possible CF-Poll headers.
uint8_t GetNBasicMcs(void) const
Return the number of basic MCS index.
EventId m_sendCtsEvent
Event to send CTS.
Definition: mac-low.h:929
MacLowRxCallback m_rxCallback
Callback to pass packet up.
Definition: mac-low.h:901
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
bool appendCfAck
Flag used for PCF to indicate whether a CF-ACK should be appended.
Definition: mac-low.h:908
EventId m_sendAckEvent
Event to send ACK.
Definition: mac-low.h:930
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
WifiMode GetControlAnswerMode(WifiMode reqMode) const
Get control answer mode function.
Definition: mac-low.cc:1287
void NotifyAckTimeoutResetNow(void)
Notify ChannelAccessManager that ACK timer should be reset.
Definition: mac-low.cc:1635
Time m_cfpMaxDuration
CFP max duration.
Definition: mac-low.h:951
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:59
Time CalculateTransmissionTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &parameters) const
Definition: mac-low.cc:1528
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
control how a packet is transmitted.
std::list< Ptr< WifiMacQueueItem > >::iterator BufferedPacketI
buffered packet iterator typedef
Definition: mac-low.h:967
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
bool IsBlockAck(void) const
Return true if the header is a Block ACK header.
bool IsMandatory(void) const
Definition: wifi-mode.cc:465
void SetCtsToSelfSupported(bool enable)
Enable or disable CTS-to-self capability.
Definition: mac-low.cc:342
bool expectCfAck
Flag used for PCF to indicate whether a CF-ACK should be expected.
Definition: mac-low.h:909
QueueEdcas m_edca
EDCA queues.
Definition: mac-low.h:982
void NormalAckTimeout(void)
Event handler when normal ACK timeout occurs.
Definition: mac-low.cc:1768
void SetBasicBlockAckTimeout(Time blockAckTimeout)
Set Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:330
phy
Definition: third.py:93
BlockAckCaches m_bAckCaches
block ack caches
Definition: mac-low.h:979
uint16_t GetChannelWidth(void) const
Definition: wifi-phy.cc:1388
Ptr< WifiMac > m_mac
Pointer to WifiMac (to fetch configuration)
Definition: mac-low.h:899
WifiPreamble GetPreambleType(void) const
void RemovePhyMacLowListener(Ptr< WifiPhy > phy)
Remove current WifiPhy listener for this MacLow.
Definition: mac-low.cc:162
uint8_t GetTid(void) const
Return the Traffic ID (TID).
bool IsBlockAckReq(void) const
Return true if the header is a Block ACK Request header.
uint8_t GetNMcs(void) const
The WifiPhy::GetNMcs() method is used (e.g., by a WifiRemoteStationManager) to determine the set of t...
Definition: wifi-phy.cc:3926
static Time CalculateTxDuration(uint32_t size, WifiTxVector txVector, uint16_t frequency)
Definition: wifi-phy.cc:2412
bool IsPromisc(void) const
Check if MacLow is operating in promiscuous mode.
Definition: mac-low.cc:480
void NotifyOn(void)
Notify listeners that we went to switch on.
Definition: mac-low.cc:102
WifiTxVector m_currentTxVector
TXVECTOR used for the current packet transmission.
Definition: mac-low.h:985
bool GetShortPreambleEnabled(void) const
Return whether the device uses short PLCP preambles.
void DestroyBlockAckAgreement(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2273
Time m_lastNavDuration
The duration of the latest NAV.
Definition: mac-low.h:954
bool IsImmediateBlockAck(void) const
Return whether the Block ACK policy is immediate Block ACK.
void SetCfpMaxDuration(Time duration)
Definition: mac-low.cc:390
Time GetCtsDuration(WifiTxVector ctsTxVector) const
Return the time required to transmit the CTS (including preamble and FCS).
Definition: mac-low.cc:1238
bool IsWithinSizeAndTimeLimits(Ptr< const WifiMacQueueItem > mpdu, WifiTxVector txVector, uint32_t ampduSize, Time ppduDurationLimit)
Check whether the given MPDU, if transmitted according to the given TX vector, meets the constraint o...
Definition: mac-low.cc:657
void SendCtsToSelf(void)
Send CTS for a CTS-to-self mechanism.
Definition: mac-low.cc:1989
bool m_ctsToSelfSupported
Flag whether CTS-to-self is supported.
Definition: mac-low.h:984
void SendAckAfterData(Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
Send ACK after receiving DATA.
Definition: mac-low.cc:2133
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1390
Mac48Address GetAddress(void) const
Return the MAC address of this MacLow.
Definition: mac-low.cc:408
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void StartTransmission(Ptr< WifiMacQueueItem > mpdu, MacLowTransmissionParameters parameters, Ptr< Txop > txop)
Definition: mac-low.cc:498
#define max(a, b)
Definition: 80211b.c:43
void CreateBlockAckAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address originator, uint16_t startingSeq)
Definition: mac-low.cc:2231
Time m_lastBeacon
The time when the last beacon frame transmission started.
Definition: mac-low.h:957
bool IsQosNoAck(void) const
Return if the QoS ACK policy is No ACK.
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
Time GetCompressedBlockAckTimeout(void) const
Return Compressed Block ACK timeout of this MacLow.
Definition: mac-low.cc:426
void ReportRtsFailed(Mac48Address address, const WifiMacHeader *header)
Should be invoked whenever the RtsTimeout associated to a transmission attempt expires.
bool IsBeacon(void) const
Return true if the header is a Beacon header.
bool GetPcfSupported(void) const
Return whether the device has PCF capability support enabled.
uint16_t GetTimeout(void) const
Return the timeout.
Listener for PHY events.
Definition: mac-low.cc:57
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1088
receive notifications about phy events.
void CtsTimeout(void)
Event handler when CTS timeout occurs.
Definition: mac-low.cc:1746
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
void DeaggregateAmpduAndReceive(Ptr< WifiPsdu > aggregatedPacket, double rxSnr, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Definition: mac-low.cc:2557
static const uint16_t MAX_MSDU_SIZE
This value conforms to the 802.11 specification.
Time GetSifs(void) const
Return Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:438
void EndTxNoAck(void)
A transmission that does not require an ACK has completed.
Definition: mac-low.cc:2114
void SetAmpduExist(Mac48Address dest, bool enableAmpdu)
Set indication whether A-MPDU is used to transmit data to a peer station.
Definition: qos-txop.cc:1518
uint32_t GetSerializedSize(void) const
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:2430
std::map< AgreementKey, BlockAckCache >::iterator BlockAckCachesI
block ack caches iterator typedef
Definition: mac-low.h:976
virtual bool IsCfPeriod(void) const
This function indicates whether Simulator::Now is in the CF period.
Definition: mac-low.cc:2664
void SetAckTimeout(Time ackTimeout)
Set ACK timeout of this MacLow.
Definition: mac-low.cc:324
bool GetHtSupported(void) const
Return whether the device has HT capability support enabled.
static TypeId GetTypeId(void)
Register this type.
Definition: mac-low.cc:144
mac
Definition: third.py:99
uint16_t ConvertGuardIntervalToNanoSeconds(WifiMode mode, const Ptr< WifiNetDevice > device)
Convert the guard interval to nanoseconds based on the wifimode.
Definition: wifi-utils.cc:71
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:32
bool StoreMpduIfNeeded(Ptr< WifiMacQueueItem > mpdu)
Definition: mac-low.cc:2204
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
Time GetCtsTimeout(void) const
Return CTS timeout of this MacLow.
Definition: mac-low.cc:432
bool IsCts(void) const
Return true if the header is a CTS header.
WifiMode GetMode(void) const
HT PHY (Clause 20)
Definition: wifi-mode.h:58
void NavCounterResetCtsMissed(Time rtsEndRxTime)
Reset NAV after CTS was missed when the NAV was set with RTS.
Definition: mac-low.cc:1587
Ptr< WifiRemoteStationManager > m_stationManager
Pointer to WifiRemoteStationManager (rate control)
Definition: mac-low.h:900
void SetMac(const Ptr< WifiMac > mac)
Set up WifiMac associated with this MacLow.
Definition: mac-low.cc:280
Headers for Block ack response.
Definition: ctrl-headers.h:193
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1610
void SendDataAfterCts(Time duration)
Send DATA after receiving CTS.
Definition: mac-low.cc:2058
void RegisterEdcaForAc(AcIndex ac, Ptr< QosTxop > edca)
Definition: mac-low.cc:2551
Agreements m_bAckAgreements
block ack agreements
Definition: mac-low.h:978
bool IsCompressed(void) const
Check if the current ACK policy is compressed ACK and not multiple TID.
bool IsExtendedCompressed(void) const
Check if the current BA policy is extended compressed block ACK.
virtual WifiTxVector GetDataTxVector(Ptr< const WifiMacQueueItem > item) const
Return a TXVECTOR for the DATA frame given the destination.
Definition: mac-low.cc:1252
virtual bool IsQosTxop() const
Check for QoS TXOP.
Definition: txop.cc:865
void NotifySwitchingStartNow(Time duration)
Definition: mac-low.cc:740
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:494
void NotifyOff(void)
Notify listeners that we went to switch off.
Definition: mac-low.cc:95
Time GetCfpMaxDuration(void) const
Definition: mac-low.cc:474
Time m_slotTime
Slot duration.
Definition: mac-low.h:946
#define list
bool IsQosAck(void) const
Return if the QoS ACK policy is Normal ACK.
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:1445
WifiMode GetDefaultMode(void) const
Return the default transmission mode.
Mac48Address GetPeer(void) const
Return the peer address.
bool m_promisc
Flag if the device is operating in promiscuous mode.
Definition: mac-low.h:960
void NotifyRxStart(Time duration)
Definition: mac-low.cc:72
void SetNss(uint8_t nss)
Sets the number of Nss refer to IEEE 802.11n Table 20-28 for explanation and range.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
void CancelAllEvents(void)
Cancel all scheduled events.
Definition: mac-low.cc:196
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:1429
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
void BlockAckTimeout(void)
Event handler when block ACK timeout occurs.
Definition: mac-low.cc:1781
void NotifyCtsTimeoutStartNow(Time duration)
Notify ChannelAccessManager that CTS timer should be started for the given duration.
Definition: mac-low.cc:1644
bool IsCfAck(void) const
Return true if the header is a CF-ACK header.
void SetNoRetry(void)
Un-set the Retry bit in the Frame Control field.
Time GetAckTimeout(void) const
Return ACK timeout of this MacLow.
Definition: mac-low.cc:414
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Time GetRemainingCfpDuration(void) const
Definition: mac-low.cc:2655
void GotCfEnd(void)
Event handler when a CF-END frame is received.
Definition: txop.cc:702
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
void RegisterDcf(Ptr< ChannelAccessManager > dcf)
Definition: mac-low.cc:492
bool IsData(void) const
Return true if the Type is DATA.
void SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
void SetBssid(Mac48Address ad)
Set the Basic Service Set Identification.
Definition: mac-low.cc:396
Time GetBasicBlockAckTimeout(void) const
Return Basic Block ACK timeout of this MacLow.
Definition: mac-low.cc:420
uint16_t GetFrequency(void) const
Definition: wifi-phy.cc:1368
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
EventId m_waitIfsEvent
Wait for IFS event.
Definition: mac-low.h:932
void EnableAck(void)
Wait ACKTimeout for an ACK.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
Time GetDuration(void) const
Return the duration from the Duration/ID field (Time object).
virtual void MissedBlockAck(uint8_t nMpdus)
Event handler when a Block ACK timeout has occurred.
Definition: txop.cc:883
void NotifyMissedCts(std::list< Ptr< WifiMacQueueItem >> mpduList)
Event handler when a CTS timeout has occurred.
Definition: qos-txop.cc:711
EventId m_normalAckTimeoutEvent
Normal ACK timeout event.
Definition: mac-low.h:926
bool IsHigherCodeRate(WifiMode mode) const
Definition: wifi-mode.cc:589
void StartDataTxTimers(WifiTxVector dataTxVector)
Start a DATA timer by scheduling appropriate ACK timeout.
Definition: mac-low.cc:1831
void NotifyWakeup(void)
Notify listeners that we woke up.
Definition: mac-low.cc:99
void SetType(BlockAckType type)
Set the block ACK type.
Time m_beaconInterval
Expected interval between two beacon transmissions.
Definition: mac-low.h:950
uint16_t GetChannelWidthForTransmission(WifiMode mode, uint16_t maxSupportedChannelWidth)
Return the channel width that corresponds to the selected mode (instead of letting the PHY&#39;s default ...
Definition: wifi-utils.cc:109
bool UseGreenfieldForDestination(Mac48Address dest) const
bool IsMultiTid(void) const
Check if the current ACK policy has multiple TID.
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:225
an EUI-48 address
Definition: mac48-address.h:43
bool IsBasic(void) const
Check if the current ACK policy is basic (i.e.
Time m_cfpForeshortening
The delay the current CF period should be foreshortened.
Definition: mac-low.h:958
void NotifyTxStart(Time duration, double txPowerDbm)
Definition: mac-low.cc:81
std::pair< BlockAckAgreement, std::list< Ptr< WifiMacQueueItem > > > AgreementValue
agreement value typedef
Definition: mac-low.h:970
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
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:2382
Time GetAckDuration(WifiTxVector ackTxVector) const
Return the time required to transmit the ACK (including preamble and FCS).
Definition: mac-low.cc:1208
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
Time m_ackTimeout
ACK timeout duration.
Definition: mac-low.h:941
bool IsAllowedControlAnswerModulationClass(WifiModulationClass modClassReq, WifiModulationClass modClassAnswer)
Return whether the modulation class of the selected mode for the control answer frame is allowed...
Definition: wifi-utils.cc:158
bool IsGroup(void) const
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:193
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:928
void RxCompleteBufferedPacketsWithSmallerSequence(uint16_t seq, Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2289
void SendCtsAfterRts(Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
Send CTS after receiving RTS.
Definition: mac-low.cc:2028
uint32_t GetBlockAckRequestSize(BlockAckType type)
Return the total Block Ack Request size (including FCS trailer).
Definition: wifi-utils.cc:199
Ptr< MsduAggregator > GetMsduAggregator(void) const
Returns the aggregator used to construct A-MSDU subframes.
Definition: mac-low.cc:292
Time GetBlockAckRequestDuration(WifiTxVector blockAckReqTxVector, BlockAckType type) const
Return the time required to transmit the Block Ack Request to the specified address given the TXVECTO...
Definition: mac-low.cc:1225
Time m_basicBlockAckTimeout
Basic block ACK timeout duration.
Definition: mac-low.h:942
void UpdateCurrentPacket(Ptr< WifiMacQueueItem > mpdu)
Update the current packet this QosTxop is trying to transmit.
Definition: qos-txop.cc:492
bool GetCtsToSelfSupported(void) const
Return whether CTS-to-self capability is supported.
Definition: mac-low.cc:348
Time m_sifs
Short Interframe Space (SIFS) duration.
Definition: mac-low.h:945
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetBeaconInterval(Time interval)
Definition: mac-low.cc:384
void SetDelayedBlockAck(void)
Set Block ACK policy to delayed ACK.
uint8_t GetNModes(void) const
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
Definition: wifi-phy.cc:3914
void NotifySleep(void)
Notify listeners that we went to sleep.
Definition: mac-low.cc:91
uint32_t GetCtsSize(void)
Return the total CTS size (including FCS trailer).
Definition: wifi-utils.cc:217
Time m_lastNavStart
The time when the latest NAV started.
Definition: mac-low.h:953
EventId m_inactivityEvent
inactivity event
bool NeedCtsToSelf(WifiTxVector txVector)
Return if we need to do Cts-to-self before sending a DATA.
void SetAmsduSupport(bool supported)
Enable or disable A-MSDU support.
uint16_t GetRawDuration(void) const
Return the raw duration from the Duration/ID field.
Ptr< WifiMacQueueItem > DequeuePeekedFrame(Ptr< const WifiMacQueueItem > peekedItem, WifiTxVector txVector, bool aggregate=true, uint32_t ampduSize=0, Time ppduDurationLimit=Time::Min())
Dequeue the frame that has been previously peeked by calling PeekNextFrame.
Definition: qos-txop.cc:318
uint8_t GetNBasicModes(void) const
Return the number of basic modes we support.
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
handle RTS/CTS/DATA/ACK transactions.
Definition: mac-low.h:59
Mac48Address address
Address of the station to be acknowledged.
Definition: mac-low.h:910
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:454
WifiMode GetMode(uint8_t mode) const
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
Definition: wifi-phy.cc:3920
bool IsQosBlockAck(void) const
Return if the QoS ACK policy is Block ACK.
EventId m_sendDataEvent
Event to send DATA.
Definition: mac-low.h:931
bool IsStateTx(void) const
Definition: wifi-phy.cc:3986
void NotifyRxEndError(void)
We have received the last bit of a packet for which NotifyRxStart was invoked first and...
Definition: mac-low.cc:78
MacLowTransmissionParameters m_txParams
Transmission parameters of the current packet.
Definition: mac-low.h:938
void SetRifs(Time rifs)
Set Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:378
void DoDispose(void)
Destructor implementation.
Definition: mac-low.cc:173
WifiTxVector GetDataTxVector(Mac48Address address, const WifiMacHeader *header, Ptr< const Packet > packet)
void SetMsduAggregator(const Ptr< MsduAggregator > aggr)
Set the aggregator used to construct A-MSDU subframes.
Definition: mac-low.cc:304
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:1483
bool IsMgt(void) const
Return true if the Type is Management.
WifiModulationClass
This enumeration defines the modulation classes per (Table 9-4 "Modulation classes"; IEEE 802...
Definition: wifi-mode.h:36
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
Time GetPpduMaxTime(WifiPreamble preamble)
Get the maximum PPDU duration (see Section 10.14 of 802.11-2016) for the PHY layers defining the aPPD...
Definition: wifi-utils.cc:254
void ReceiveOk(Ptr< WifiMacQueueItem > mpdu, double rxSnr, WifiTxVector txVector, bool ampduSubframe)
Definition: mac-low.cc:786
Mac48Address m_self
Address of this MacLow (Mac48Address)
Definition: mac-low.h:939
Maintains information for a block ack agreement.
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:1461
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:863
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:73
void NotifyAckTimeoutStartNow(Time duration)
Notify ChannelAccessManager that ACK timer should be started for the given duration.
Definition: mac-low.cc:1626
bool CanTransmitNextCfFrame(void) const
This function decides if a CF frame can be transmitted in the current CFP.
Definition: mac-low.cc:2670
void SetSlotTime(Time slotTime)
Set slot duration of this MacLow.
Definition: mac-low.cc:366
virtual void GotAck(void)
Event handler when an ACK is received.
Definition: txop.cc:642
bool IsAmsduSupported(void) const
Return whether A-MSDU capability is supported.
bool IsPositive(void) const
Definition: nstime.h:298
bool IsProbeResp(void) const
Return true if the header is a Probe Response header.
void Reset(void)
Reset the station, invoked in a STA upon dis-association or in an AP upon reboot. ...
bool GetUseNonErpProtection(void) const
Return whether the device supports protection of non-ERP stations.
virtual void MissedCts(void)
Event handler when a CTS timeout has occurred.
Definition: txop.cc:615
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:870
Implement the header for management frames of type add block ack response.
Definition: mgt-headers.h:1135
Time m_cfpStart
The time when the latest CF period started.
Definition: mac-low.h:956
ns3::MacLow * m_macLow
the MAC
Definition: mac-low.cc:107
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
uint32_t GetBlockAckSize(BlockAckType type)
Return the total Block ACK size (including FCS trailer).
Definition: wifi-utils.cc:189
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1064
Ptr< const WifiMacQueueItem > PrepareBlockAckRequest(Mac48Address recipient, uint8_t tid) const
Definition: qos-txop.cc:146
std::map< AgreementKey, AgreementValue >::iterator AgreementsI
agreements iterator
Definition: mac-low.h:973
uint32_t GetSerializedSize(void) const
EventId m_endTxNoAckEvent
Event for finishing transmission that does not require ACK.
Definition: mac-low.h:933
virtual Time GetTxopRemaining(void) const
Return the remaining duration in the current TXOP.
Definition: txop.cc:889
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
void MissedCfPollResponse(bool expectedCfAck)
Event handler when a response to a CF-POLL frame is missed.
Definition: txop.cc:716
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:1215
CfAckInfo m_cfAckInfo
Info about piggyback ACKs used in PCF.
Definition: mac-low.h:987
void SetMpduAggregator(const Ptr< MpduAggregator > aggr)
Set the aggregator used to construct A-MPDU subframes.
Definition: mac-low.cc:311
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:75
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:354
void Send(Ptr< const WifiPsdu > psdu, WifiTxVector txVector)
Definition: wifi-phy.cc:2536
void SetImmediateBlockAck(void)
Set Block ACK policy to immediate ACK.
bool IsRts(void) const
Return true if the header is a RTS header.
void DisableNextData(void)
Do not attempt to send data burst after current transmission.
BlockAckType GetType(void) const
Return the block ACK type ID.
void SendDataPacket(void)
Send DATA packet, which can be DATA-ACK or RTS-CTS-DATA-ACK transaction.
Definition: mac-low.cc:1893
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS DATA...
void SetTimeout(uint16_t timeout)
Set timeout.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1080
Time GetPifs(void) const
Return PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:456
bool IsAck(void) const
Return true if the header is an ACK header.
void SetAddress(Mac48Address ad)
Set MAC address of this MacLow.
Definition: mac-low.cc:318
uint32_t GetCfEndSize(void) const
Return the total CF-END size (including FCS trailer).
Definition: mac-low.cc:1186
void ForwardDown(Ptr< const WifiPsdu > psdu, WifiTxVector txVector)
Forward a PSDU down to WifiPhy for transmission.
Definition: mac-low.cc:1662
second
Definition: nstime.h:114
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:2100
void SetRxCallback(Callback< void, Ptr< WifiMacQueueItem >> callback)
Definition: mac-low.cc:486
PhyMacLowListener(ns3::MacLow *macLow)
Create a PhyMacLowListener for the given MacLow.
Definition: mac-low.cc:65
Time GetBeaconInterval(void) const
Definition: mac-low.cc:468
Time m_compressedBlockAckTimeout
Compressed block ACK timeout duration.
Definition: mac-low.h:943
void CfPollTimeout(void)
Event handler when CF-POLL timeout occurs.
Definition: mac-low.cc:1728
virtual void TerminateTxop(void)
Update backoff and restart access if needed.
Definition: txop.cc:896
void NotifyCtsTimeoutResetNow(void)
Notify ChannelAccessManager that CTS timer should be reset.
Definition: mac-low.cc:1653
Headers for Block ack request.
Definition: ctrl-headers.h:41
WifiMode GetBasicMode(uint8_t i) const
Return a basic mode from the set of basic modes.
Ptr< WifiPsdu > m_currentPacket
Current packet transmitted/to be transmitted.
Definition: mac-low.h:936
virtual ~PhyMacLowListener()
Definition: mac-low.cc:69
void ResetPhy(void)
Remove WifiPhy associated with this MacLow.
Definition: mac-low.cc:263
virtual void GotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, WifiMode txMode, double dataSnr)
Event handler when a Block ACK is received.
Definition: txop.cc:877
void DisableAck(void)
Do not wait for Ack after data transmission.
Time GetSlotTime(void) const
Return slot duration of this MacLow.
Definition: mac-low.cc:450
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:1477
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
a unique identifier for an interface.
Definition: type-id.h:58
bool IsHigherDataRate(WifiMode mode) const
Definition: wifi-mode.cc:609
BlockAckCache cache.
uint16_t GetStartingSequenceControl(void) const
Return the starting sequence control.
bool NeedCtsToSelf(void) const
Check if CTS-to-self mechanism should be used for the current packet.
Definition: mac-low.cc:650
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Time GetLastRxStartTime(void) const
Return the start time of the last received packet.
Definition: wifi-phy.cc:4016
uint8_t GetTid(void) const
Return the Traffic ID (TID).
bool IsStateRx(void) const
Definition: wifi-phy.cc:3980
Time m_rifs
Reduced Interframe Space (RIFS) duration.
Definition: mac-low.h:948
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:38
Introspection did not find any typical Config paths.
Definition: snr-tag.h:34
HE PHY (Clause 26)
Definition: wifi-mode.h:62
virtual ~MacLow()
Definition: mac-low.cc:137
Ptr< MpduAggregator > m_mpduAggregator
A-MPDU aggregator.
Definition: mac-low.h:924
Ptr< WifiPhy > m_phy
Pointer to WifiPhy (actually send/receives frames)
Definition: mac-low.h:898
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:150
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:286
Implements the IEEE 802.11 MAC header.
bool IsNegative(void) const
Definition: nstime.h:293
void SetCompressedBlockAckTimeout(Time blockAckTimeout)
Set Compressed Block ACK timeout of this MacLow.
Definition: mac-low.cc:336
Implements the IEEE 802.11 MAC trailer.
Ptr< WifiPhy > GetPhy(void) const
Definition: mac-low.cc:257
class PhyMacLowListener * m_phyMacLowListener
Listener needed to monitor when a channel switching occurs.
Definition: mac-low.h:962
ChannelAccessManagers m_channelAccessManagers
List of ChannelAccessManager.
Definition: mac-low.h:921
bool HasData(void) const
Return true if the header type is DATA and is not DATA_NULL.
uint16_t GetSequenceControl(void) const
Return the raw Sequence Control field.
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:1791
BlockAckType
The different block ACK policies.
void RxCompleteBufferedPacketsUntilFirstLost(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2352
Time GetGuardInterval(void) const
Definition: wifi-phy.cc:696
Time GetTxopLimit(void) const
Return the TXOP limit.
Definition: txop.cc:302