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