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  if (psduDuration.IsZero ())
654  {
655  //PHY-RXEND immediately follows PHY-RXSTART (e.g. when PPDU has been filtered), no need to reschedule timeouts (CCA will take over)
656  return;
657  }
658  NS_ASSERT (psduDuration.IsStrictlyPositive ());
659 
661  {
662  // we are waiting for a Normal Ack and something arrived
663  NS_LOG_DEBUG ("Rescheduling Normal Ack timeout");
667  &MacLow::NormalAckTimeout, this);
668  }
669  else if (m_blockAckTimeoutEvent.IsRunning ())
670  {
671  // we are waiting for a BlockAck and something arrived
672  NS_LOG_DEBUG ("Rescheduling Block Ack timeout");
676  &MacLow::BlockAckTimeout, this);
677  }
678  else if (m_ctsTimeoutEvent.IsRunning ())
679  {
680  // we are waiting for a CTS and something arrived
681  NS_LOG_DEBUG ("Rescheduling CTS timeout");
685  &MacLow::CtsTimeout, this);
686  }
688  {
689  NS_LOG_DEBUG ("Cannot reset NAV");
691  }
692 }
693 
694 void
696 {
697  NS_LOG_FUNCTION (this << *psdu);
698  NS_LOG_DEBUG ("rx failed");
699  if (IsCfPeriod () && m_currentPacket->GetHeader (0).IsCfPoll ())
700  {
701  NS_ASSERT (m_currentTxop != 0);
703  }
704  else if (m_cfAckInfo.expectCfAck)
705  {
706  NS_ASSERT (m_currentTxop != 0);
707  Ptr<Txop> txop = m_currentTxop;
708  m_currentTxop = 0;
709  txop->MissedAck ();
710  }
711  m_cfAckInfo.expectCfAck = false;
712  return;
713 }
714 
715 void
717 {
718  NS_LOG_DEBUG ("switching channel. Cancelling MAC pending events");
720  CancelAllEvents ();
722  {
724  }
727  m_currentPacket = 0;
728  m_currentTxop = 0;
729 }
730 
731 void
733 {
734  NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
735  CancelAllEvents ();
737  {
739  }
742  m_currentPacket = 0;
743  m_currentTxop = 0;
744 }
745 
746 void
748 {
749  NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events");
750  CancelAllEvents ();
752  {
754  }
757  m_currentPacket = 0;
758  m_currentTxop = 0;
759 }
760 
761 void
762 MacLow::ReceiveOk (Ptr<WifiMacQueueItem> mpdu, double rxSnr, WifiTxVector txVector, bool ampduSubframe)
763 {
764  NS_LOG_FUNCTION (this << *mpdu << rxSnr << txVector);
765  /* An MPDU is received from the PHY.
766  * When we have handled this MPDU,
767  * we handle any packet present in the
768  * packet queue.
769  */
770  const WifiMacHeader& hdr = mpdu->GetHeader ();
771  Ptr<Packet> packet = mpdu->GetPacket ()->Copy ();
772 
773  bool isPrevNavZero = IsNavZero ();
774  NS_LOG_DEBUG ("duration/id=" << hdr.GetDuration ());
775  NotifyNav (packet, hdr);
776  if (hdr.IsRts ())
777  {
778  /* see section 9.2.5.7 802.11-1999
779  * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS
780  * period if the NAV at the STA receiving the RTS frame indicates that the medium is
781  * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle,
782  * that STA shall not respond to the RTS frame.
783  */
784  if (ampduSubframe)
785  {
786  NS_FATAL_ERROR ("Received RTS as part of an A-MPDU");
787  }
788  else
789  {
790  if (isPrevNavZero
791  && hdr.GetAddr1 () == m_self)
792  {
793  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
796  rxSnr, txVector.GetMode ());
799  hdr.GetAddr2 (),
800  hdr.GetDuration (),
801  txVector,
802  rxSnr);
803  }
804  else
805  {
806  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
807  }
808  }
809  }
810  else if (hdr.IsCts ()
811  && hdr.GetAddr1 () == m_self
813  && m_currentPacket != 0)
814  {
815  if (ampduSubframe)
816  {
817  NS_FATAL_ERROR ("Received CTS as part of an A-MPDU");
818  }
819 
820  NS_LOG_DEBUG ("received cts from=" << m_currentPacket->GetAddr1 ());
821 
822  SnrTag tag;
823  packet->RemovePacketTag (tag);
825  rxSnr, txVector.GetMode ());
826  m_stationManager->ReportRtsOk (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0),
827  rxSnr, txVector.GetMode (), tag.Get ());
828 
834  hdr.GetDuration ());
835  }
836  else if (hdr.IsAck ()
837  && hdr.GetAddr1 () == m_self
840  {
841  NS_LOG_DEBUG ("receive ack from=" << m_currentPacket->GetAddr1 ());
842  SnrTag tag;
843  packet->RemovePacketTag (tag);
844  //When fragmentation is used, only update manager when the last fragment is acknowledged
845  if (!m_txParams.HasNextPacket ())
846  {
848  rxSnr, txVector.GetMode ());
849  m_stationManager->ReportDataOk (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0),
850  rxSnr, txVector.GetMode (), tag.Get (),
851  m_currentTxVector, m_currentPacket->GetSize ());
852  }
853  // cancel the Normal Ack timer
856  m_currentTxop->GotAck ();
857 
858  if (m_txParams.HasNextPacket ())
859  {
861  }
862  else if (m_currentPacket->GetHeader (0).IsQosData () && m_currentTxop->IsQosTxop () &&
864  {
866  }
867  else if (m_currentTxop->IsQosTxop ())
868  {
870  }
871  }
872  else if (hdr.IsBlockAck () && hdr.GetAddr1 () == m_self
875  {
876  NS_LOG_DEBUG ("got block ack from " << hdr.GetAddr2 ());
877  SnrTag tag;
878  packet->RemovePacketTag (tag);
879  CtrlBAckResponseHeader blockAck;
880  packet->RemoveHeader (blockAck);
883  m_currentTxop->GotBlockAck (&blockAck, hdr.GetAddr2 (), rxSnr, tag.Get (), m_currentTxVector);
884  // start next packet if TXOP remains, otherwise contend for accessing the channel again
887  {
889  }
890  else if (m_currentTxop->IsQosTxop ())
891  {
893  }
894  }
895  else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
896  {
897  m_stationManager->ReportRxOk (hdr.GetAddr2 (), rxSnr, txVector.GetMode ());
898 
899  CtrlBAckRequestHeader blockAckReq;
900  packet->RemoveHeader (blockAckReq);
901  if (!blockAckReq.IsMultiTid ())
902  {
903  uint8_t tid = blockAckReq.GetTidInfo ();
904  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), tid));
905  if (it != m_bAckAgreements.end ())
906  {
907  //Update block ack cache
908  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), tid));
909  NS_ASSERT (i != m_bAckCaches.end ());
910  (*i).second.UpdateWithBlockAckReq (blockAckReq.GetStartingSequence ());
911 
912  //NS_ASSERT (m_sendAckEvent.IsExpired ());
914  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
915  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
916  if ((*it).second.first.IsImmediateBlockAck ())
917  {
918  NS_LOG_DEBUG ("rx blockAckRequest/sendImmediateBlockAck from=" << hdr.GetAddr2 ());
921  blockAckReq,
922  hdr.GetAddr2 (),
923  hdr.GetDuration (),
924  txVector.GetMode (),
925  rxSnr);
926  }
927  else
928  {
929  NS_FATAL_ERROR ("Delayed block ack not supported.");
930  }
931  }
932  else
933  {
934  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
935  }
936  }
937  else
938  {
939  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
940  }
941  }
942  else if (hdr.IsCtl ())
943  {
944  if (hdr.IsCfEnd ())
945  {
946  NS_LOG_DEBUG ("rx CF-END ");
947  m_cfpStart = NanoSeconds (0);
949  {
950  NS_ASSERT (m_currentTxop != 0);
951  if (hdr.IsCfAck ())
952  {
953  m_currentTxop->GotAck ();
954  }
955  else
956  {
958  }
959  }
960  if (m_currentTxop != 0)
961  {
963  }
964  m_cfAckInfo.expectCfAck = false;
965  }
966  else
967  {
968  NS_LOG_DEBUG ("rx drop " << hdr.GetTypeString ());
969  }
970  }
971  else if (hdr.GetAddr1 () == m_self)
972  {
973  if (hdr.IsCfPoll ())
974  {
976  if (m_cfAckInfo.expectCfAck && !hdr.IsCfAck ())
977  {
978  NS_ASSERT (m_currentTxop != 0);
979  Ptr<Txop> txop = m_currentTxop;
980  m_currentTxop = 0;
981  txop->MissedAck ();
982  m_cfAckInfo.expectCfAck = false;
983  }
984  }
986  rxSnr, txVector.GetMode ());
987  if (hdr.IsQosData () && ReceiveMpdu (mpdu))
988  {
989  /* From section 9.10.4 in IEEE 802.11:
990  Upon the receipt of a QoS data frame from the originator for which
991  the block ack agreement exists, the recipient shall buffer the MSDU
992  regardless of the value of the Ack Policy subfield within the
993  QoS Control field of the QoS data frame. */
994  if (hdr.IsQosAck () && !ampduSubframe)
995  {
996  NS_LOG_DEBUG ("rx QoS unicast/sendAck from=" << hdr.GetAddr2 ());
997  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
998 
999  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (),
1000  hdr.GetAddr2 (), hdr.GetQosTid ());
1004  &MacLow::SendAckAfterData, this,
1005  hdr.GetAddr2 (),
1006  hdr.GetDuration (),
1007  txVector.GetMode (),
1008  rxSnr);
1009  }
1010  else if (hdr.IsQosBlockAck ())
1011  {
1012  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1013  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
1014  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
1015  }
1016  return;
1017  }
1018  else if (hdr.IsQosData () && hdr.IsQosBlockAck ())
1019  {
1020  /* This happens if a packet with ack policy Block Ack is received and a block ack
1021  agreement for that packet doesn't exist.
1022 
1023  From section 11.5.3 in IEEE 802.11e:
1024  When a recipient does not have an active block ack for a TID, but receives
1025  data MPDUs with the Ack Policy subfield set to Block Ack, it shall discard
1026  them and shall send a DELBA frame using the normal access
1027  mechanisms. */
1028  AcIndex ac = QosUtilsMapTidToAc (hdr.GetQosTid ());
1029  m_edca[ac]->SendDelbaFrame (hdr.GetAddr2 (), hdr.GetQosTid (), false);
1030  return;
1031  }
1032  else if (hdr.IsQosData () && hdr.IsQosNoAck ())
1033  {
1034  if (ampduSubframe)
1035  {
1036  NS_LOG_DEBUG ("rx Ampdu with No Ack Policy from=" << hdr.GetAddr2 ());
1037  }
1038  else
1039  {
1040  NS_LOG_DEBUG ("rx unicast/noAck from=" << hdr.GetAddr2 ());
1041  }
1042  }
1043  else if (hdr.IsData () || hdr.IsMgt ())
1044  {
1045  if (hdr.IsProbeResp ())
1046  {
1047  // Apply SNR tag for probe response quality measurements
1048  SnrTag tag;
1049  tag.Set (rxSnr);
1050  packet->AddPacketTag (tag);
1051  mpdu = Create<WifiMacQueueItem> (packet, hdr);
1052  }
1053  if (hdr.IsMgt () && ampduSubframe)
1054  {
1055  NS_FATAL_ERROR ("Received management packet as part of an A-MPDU");
1056  }
1057  else
1058  {
1059  if (IsCfPeriod ())
1060  {
1061  if (hdr.HasData ())
1062  {
1063  m_cfAckInfo.appendCfAck = true;
1064  m_cfAckInfo.address = hdr.GetAddr2 ();
1065  }
1066  }
1067  else
1068  {
1069  NS_LOG_DEBUG ("rx unicast/sendAck from=" << hdr.GetAddr2 ());
1072  &MacLow::SendAckAfterData, this,
1073  hdr.GetAddr2 (),
1074  hdr.GetDuration (),
1075  txVector.GetMode (),
1076  rxSnr);
1077  }
1078  }
1079  }
1080  goto rxPacket;
1081  }
1082  else if (hdr.GetAddr1 ().IsGroup ())
1083  {
1084  if (ampduSubframe)
1085  {
1086  NS_FATAL_ERROR ("Received group addressed packet as part of an A-MPDU");
1087  }
1088  else
1089  {
1090  if (hdr.IsData () || hdr.IsMgt ())
1091  {
1092  NS_LOG_DEBUG ("rx group from=" << hdr.GetAddr2 ());
1093  if (hdr.IsBeacon ())
1094  {
1095  // Apply SNR tag for beacon quality measurements
1096  SnrTag tag;
1097  tag.Set (rxSnr);
1098  packet->AddPacketTag (tag);
1099  mpdu = Create<WifiMacQueueItem> (packet, hdr);
1100  }
1101  goto rxPacket;
1102  }
1103  }
1104  }
1105  else if (m_promisc)
1106  {
1107  NS_ASSERT (hdr.GetAddr1 () != m_self);
1108  if (hdr.IsData ())
1109  {
1110  goto rxPacket;
1111  }
1112  }
1113  else
1114  {
1115  if (m_cfAckInfo.expectCfAck && hdr.IsCfAck ())
1116  {
1117  m_cfAckInfo.expectCfAck = false;
1118  NS_ASSERT (m_currentTxop != 0);
1119  m_currentTxop->GotAck ();
1120  }
1121  NS_LOG_DEBUG ("rx not for me from=" << hdr.GetAddr2 ());
1122  }
1123  return;
1124 rxPacket:
1125  if (m_cfAckInfo.expectCfAck && hdr.IsCfAck ())
1126  {
1127  m_cfAckInfo.expectCfAck = false;
1128  NS_ASSERT (m_currentTxop != 0);
1129  m_currentTxop->GotAck ();
1130  }
1131  m_rxCallback (mpdu);
1132  return;
1133 }
1134 
1135 uint32_t
1137 {
1138  WifiMacHeader cfEnd;
1140  {
1141  cfEnd.SetType (WIFI_MAC_CTL_END_ACK);
1142  }
1143  else
1144  {
1145  cfEnd.SetType (WIFI_MAC_CTL_END);
1146  }
1147  return cfEnd.GetSize () + 4;
1148 }
1149 
1150 Time
1152 {
1153  WifiTxVector ackTxVector = GetAckTxVectorForData (to, dataTxVector.GetMode ());
1154  return GetAckDuration (ackTxVector);
1155 }
1156 
1157 Time
1159 {
1160  NS_ASSERT (ackTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //Ack should always use non-HT PPDU (HT PPDU cases not supported yet)
1161  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetPhyBand ());
1162 }
1163 
1164 Time
1165 MacLow::GetBlockAckDuration (WifiTxVector blockAckReqTxVector, BlockAckType type) const
1166 {
1167  /*
1168  * For immediate Basic BlockAck we should transmit the frame with the same WifiMode
1169  * as the BlockAckReq.
1170  */
1171  return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, m_phy->GetPhyBand ());
1172 }
1173 
1174 Time
1176 {
1177  return m_phy->CalculateTxDuration (GetBlockAckRequestSize (type), blockAckReqTxVector, m_phy->GetPhyBand ());
1178 }
1179 
1180 Time
1182 {
1183  WifiTxVector ctsTxVector = GetCtsTxVectorForRts (to, rtsTxVector.GetMode ());
1184  return GetCtsDuration (ctsTxVector);
1185 }
1186 
1187 Time
1189 {
1190  NS_ASSERT (ctsTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1191  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetPhyBand ());
1192 }
1193 
1196 {
1197  return m_stationManager->GetRtsTxVector (item->GetHeader ().GetAddr1 ());
1198 }
1199 
1202 {
1203  return m_stationManager->GetDataTxVector (item->GetHeader ());
1204 }
1205 
1206 Time
1208  Mac48Address receiver) const
1209 {
1210  NS_LOG_FUNCTION (this << receiver << dataTxVector << params);
1211 
1212  Time duration = Seconds (0);
1213  if (params.MustWaitNormalAck ())
1214  {
1215  duration += GetSifs ();
1216  duration += GetAckDuration (receiver, dataTxVector);
1217  }
1218  else if (params.MustWaitBlockAck ())
1219  {
1220  duration += GetSifs ();
1221  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_self, dataTxVector.GetMode ());
1222  duration += GetBlockAckDuration (blockAckReqTxVector, params.GetBlockAckType ());
1223  }
1224  else if (params.MustSendBlockAckRequest ())
1225  {
1226  duration += 2 * GetSifs ();
1227  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_self, dataTxVector.GetMode ());
1228  duration += GetBlockAckRequestDuration (blockAckReqTxVector, params.GetBlockAckRequestType ());
1229  duration += GetBlockAckDuration (blockAckReqTxVector, params.GetBlockAckRequestType ());
1230  }
1231  return duration;
1232 }
1233 
1234 WifiMode
1236 {
1251  NS_LOG_FUNCTION (this << reqMode);
1253  bool found = false;
1254  //First, search the BSS Basic Rate set
1255  for (uint8_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
1256  {
1257  WifiMode testMode = m_stationManager->GetBasicMode (i);
1258  if ((!found || testMode.IsHigherDataRate (mode))
1259  && (!testMode.IsHigherDataRate (reqMode))
1261  {
1262  mode = testMode;
1263  //We've found a potentially-suitable transmit rate, but we
1264  //need to continue and consider all the basic rates before
1265  //we can be sure we've got the right one.
1266  found = true;
1267  }
1268  }
1270  {
1271  if (!found)
1272  {
1273  mode = m_stationManager->GetDefaultMcs ();
1274  for (uint8_t i = 0; i != m_stationManager->GetNBasicMcs (); i++)
1275  {
1276  WifiMode testMode = m_stationManager->GetBasicMcs (i);
1277  if ((!found || testMode.IsHigherDataRate (mode))
1278  && (!testMode.IsHigherDataRate (reqMode))
1279  && (testMode.GetModulationClass () == reqMode.GetModulationClass ()))
1280  {
1281  mode = testMode;
1282  //We've found a potentially-suitable transmit rate, but we
1283  //need to continue and consider all the basic rates before
1284  //we can be sure we've got the right one.
1285  found = true;
1286  }
1287  }
1288  }
1289  }
1290  //If we found a suitable rate in the BSSBasicRateSet, then we are
1291  //done and can return that mode.
1292  if (found)
1293  {
1294  NS_LOG_DEBUG ("MacLow::GetControlAnswerMode returning " << mode);
1295  return mode;
1296  }
1297 
1315  for (uint8_t idx = 0; idx < m_phy->GetNModes (); idx++)
1316  {
1317  WifiMode thismode = m_phy->GetMode (idx);
1318  /* If the rate:
1319  *
1320  * - is a mandatory rate for the PHY, and
1321  * - is equal to or faster than our current best choice, and
1322  * - is less than or equal to the rate of the received frame, and
1323  * - is of the same modulation class as the received frame
1324  *
1325  * ...then it's our best choice so far.
1326  */
1327  if (thismode.IsMandatory ()
1328  && (!found || thismode.IsHigherDataRate (mode))
1329  && (!thismode.IsHigherDataRate (reqMode))
1331  {
1332  mode = thismode;
1333  //As above; we've found a potentially-suitable transmit
1334  //rate, but we need to continue and consider all the
1335  //mandatory rates before we can be sure we've got the right one.
1336  found = true;
1337  }
1338  }
1340  {
1341  for (uint8_t idx = 0; idx < m_phy->GetNMcs (); idx++)
1342  {
1343  WifiMode thismode = m_phy->GetMcs (idx);
1344  if (thismode.IsMandatory ()
1345  && (!found || thismode.IsHigherDataRate (mode))
1346  && (!thismode.IsHigherCodeRate (reqMode))
1347  && (thismode.GetModulationClass () == reqMode.GetModulationClass ()))
1348  {
1349  mode = thismode;
1350  //As above; we've found a potentially-suitable transmit
1351  //rate, but we need to continue and consider all the
1352  //mandatory rates before we can be sure we've got the right one.
1353  found = true;
1354  }
1355  }
1356  }
1357 
1367  if (!found)
1368  {
1369  NS_FATAL_ERROR ("Can't find response rate for " << reqMode);
1370  }
1371 
1372  NS_LOG_DEBUG ("MacLow::GetControlAnswerMode returning " << mode);
1373  return mode;
1374 }
1375 
1378 {
1379  NS_ASSERT (!to.IsGroup ());
1380  WifiMode ctsMode = GetControlAnswerMode (rtsTxMode);
1381  WifiTxVector v;
1382  v.SetMode (ctsMode);
1386  uint16_t ctsTxGuardInterval = ConvertGuardIntervalToNanoSeconds (ctsMode, DynamicCast<WifiNetDevice> (m_phy->GetDevice ()));
1387  v.SetGuardInterval (ctsTxGuardInterval);
1388  v.SetNss (1);
1389  return v;
1390 }
1391 
1394 {
1395  NS_ASSERT (!to.IsGroup ());
1396  WifiMode ackMode = GetControlAnswerMode (dataTxMode);
1397  WifiTxVector v;
1398  v.SetMode (ackMode);
1402  uint16_t ackTxGuardInterval = ConvertGuardIntervalToNanoSeconds (ackMode, DynamicCast<WifiNetDevice> (m_phy->GetDevice ()));
1403  v.SetGuardInterval (ackTxGuardInterval);
1404  v.SetNss (1);
1405  return v;
1406 }
1407 
1410 {
1411  NS_ASSERT (!to.IsGroup ());
1412  WifiMode blockAckMode = GetControlAnswerMode (dataTxMode);
1413  WifiTxVector v;
1414  v.SetMode (blockAckMode);
1418 uint16_t blockAckTxGuardInterval = ConvertGuardIntervalToNanoSeconds (blockAckMode, DynamicCast<WifiNetDevice> (m_phy->GetDevice ()));
1419  v.SetGuardInterval (blockAckTxGuardInterval);
1420  v.SetNss (1);
1421  return v;
1422 }
1423 
1426 {
1427  return GetCtsTxVector (to, rtsTxMode);
1428 }
1429 
1432 {
1433  return GetAckTxVector (to, dataTxMode);
1434 }
1435 
1436 Time
1438  const WifiMacHeader* hdr,
1439  const MacLowTransmissionParameters& params,
1440  uint32_t fragmentSize) const
1441 {
1442  Ptr<const WifiMacQueueItem> item = Create<const WifiMacQueueItem> (packet, *hdr);
1443  Time txTime = CalculateOverheadTxTime (item, params);
1444  uint32_t dataSize;
1445  if (fragmentSize > 0)
1446  {
1447  Ptr<const Packet> fragment = Create<Packet> (fragmentSize);
1448  dataSize = GetSize (fragment, hdr, m_currentPacket && m_currentPacket->IsAggregate ());
1449  }
1450  else
1451  {
1452  dataSize = GetSize (packet, hdr, m_currentPacket && m_currentPacket->IsAggregate ());
1453  }
1454  txTime += m_phy->CalculateTxDuration (dataSize, GetDataTxVector (item), m_phy->GetPhyBand ());
1455  return txTime;
1456 }
1457 
1458 Time
1460  const MacLowTransmissionParameters& params) const
1461 {
1462  Time txTime = Seconds (0);
1463  if (params.MustSendRts ())
1464  {
1465  WifiTxVector rtsTxVector = GetRtsTxVector (item);
1466  txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetPhyBand ());
1467  txTime += GetCtsDuration (item->GetHeader ().GetAddr1 (), rtsTxVector);
1468  txTime += Time (GetSifs () * 2);
1469  }
1470  txTime += GetResponseDuration (params, GetDataTxVector (item), item->GetHeader ().GetAddr1 ());
1471 
1472  return txTime;
1473 }
1474 
1475 Time
1477  const WifiMacHeader* hdr,
1478  const MacLowTransmissionParameters& params) const
1479 {
1480  Time txTime = CalculateOverallTxTime (packet, hdr, params);
1481  if (params.HasNextPacket ())
1482  {
1483  WifiTxVector dataTxVector = GetDataTxVector (Create<const WifiMacQueueItem> (packet, *hdr));
1484  txTime += GetSifs ();
1485  txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, m_phy->GetPhyBand ());
1486  }
1487  return txTime;
1488 }
1489 
1490 void
1492 {
1494  if (hdr.GetRawDuration () > 32767)
1495  {
1496  //All stations process Duration field values less than or equal to 32 767 from valid data frames
1497  //to update their NAV settings as appropriate under the coordination function rules.
1498  return;
1499  }
1500  if (hdr.IsCfEnd () && hdr.GetAddr2 () == m_bssid)
1501  {
1502  //see section 9.3.2.2 802.11-1999
1503  DoNavResetNow (Seconds (0));
1504  return;
1505  }
1506  else if (hdr.GetAddr1 () != m_self)
1507  {
1508  // see section 9.2.5.4 802.11-1999
1509  Time duration = hdr.GetDuration ();
1510  bool navUpdated = DoNavStartNow (duration);
1511  if (hdr.IsRts () && navUpdated)
1512  {
1521  WifiMacHeader cts;
1522  cts.SetType (WIFI_MAC_CTL_CTS);
1523  WifiTxVector txVector = GetRtsTxVector (Create<const WifiMacQueueItem> (packet, hdr));
1524  Time navCounterResetCtsMissedDelay =
1525  m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, m_phy->GetPhyBand ()) +
1526  Time (2 * GetSifs ()) + Time (2 * GetSlotTime ()) +
1528  m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
1529  &MacLow::DoNavResetNow, this,
1530  Seconds (0));
1531  }
1532  }
1533 }
1534 
1535 void
1537 {
1538  NS_LOG_FUNCTION (this << duration);
1539  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1540  {
1541  (*i)->NotifyNavResetNow (duration);
1542  }
1544  m_lastNavDuration = duration;
1545 }
1546 
1547 bool
1549 {
1550  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1551  {
1552  (*i)->NotifyNavStartNow (duration);
1553  }
1554  Time newNavEnd = Simulator::Now () + duration;
1555  Time oldNavEnd = m_lastNavStart + m_lastNavDuration;
1556  if (newNavEnd > oldNavEnd)
1557  {
1559  m_lastNavDuration = duration;
1560  return true;
1561  }
1562  return false;
1563 }
1564 
1565 void
1567 {
1568  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1569  {
1570  (*i)->NotifyAckTimeoutStartNow (duration);
1571  }
1572 }
1573 
1574 void
1576 {
1577  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1578  {
1579  (*i)->NotifyAckTimeoutResetNow ();
1580  }
1581 }
1582 
1583 void
1585 {
1586  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1587  {
1588  (*i)->NotifyCtsTimeoutStartNow (duration);
1589  }
1590 }
1591 
1592 void
1594 {
1595  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1596  {
1597  (*i)->NotifyCtsTimeoutResetNow ();
1598  }
1599 }
1600 
1601 void
1603 {
1604  NS_LOG_FUNCTION (this << psdu << txVector);
1605 
1606  NS_ASSERT (psdu->GetNMpdus ());
1607  const WifiMacHeader& hdr = (*psdu->begin ())->GetHeader ();
1608 
1609  NS_LOG_DEBUG ("send " << hdr.GetTypeString () <<
1610  ", to=" << hdr.GetAddr1 () <<
1611  ", size=" << psdu->GetSize () <<
1612  ", mode=" << txVector.GetMode () <<
1613  ", preamble=" << txVector.GetPreambleType () <<
1614  ", duration=" << hdr.GetDuration () <<
1615  ", seq=0x" << std::hex << hdr.GetSequenceControl () << std::dec);
1616 
1617  if (hdr.IsCfPoll () && m_stationManager->GetPcfSupported ())
1618  {
1620  }
1621  if (hdr.IsBeacon () && m_stationManager->GetPcfSupported ())
1622  {
1624  {
1626  }
1628  }
1629  else if (hdr.IsCfEnd () && m_stationManager->GetPcfSupported ())
1630  {
1631  m_cfpStart = NanoSeconds (0);
1633  m_cfAckInfo.appendCfAck = false;
1634  m_cfAckInfo.expectCfAck = false;
1635  }
1636  else if (IsCfPeriod () && hdr.HasData ())
1637  {
1638  m_cfAckInfo.expectCfAck = true;
1639  }
1640 
1641  if (psdu->IsSingle ())
1642  {
1643  txVector.SetAggregation (true);
1644  NS_LOG_DEBUG ("Sending S-MPDU");
1645  }
1646  else if (psdu->IsAggregate ())
1647  {
1648  txVector.SetAggregation (true);
1649  NS_LOG_DEBUG ("Sending A-MPDU");
1650  }
1651  else
1652  {
1653  NS_LOG_DEBUG ("Sending non aggregate MPDU");
1654  }
1655 
1656  for (auto& mpdu : *PeekPointer (psdu))
1657  {
1658  if (mpdu->GetHeader ().IsQosData ())
1659  {
1660  auto edcaIt = m_edca.find (QosUtilsMapTidToAc (mpdu->GetHeader ().GetQosTid ()));
1661  edcaIt->second->CompleteMpduTx (mpdu);
1662  }
1663  }
1664  m_phy->Send (psdu, txVector);
1665 }
1666 
1667 void
1669 {
1670  NS_LOG_FUNCTION (this);
1671  //to be reworked
1672  bool busy = false;
1673  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1674  {
1675  busy = (*i)->IsBusy ();
1676  }
1677  if (!busy)
1678  {
1679  NS_ASSERT (m_currentTxop != 0);
1681  m_cfAckInfo.expectCfAck = false;
1682  }
1683 }
1684 
1685 void
1687 {
1688  NS_LOG_FUNCTION (this);
1689  NS_LOG_DEBUG ("cts timeout");
1693  m_stationManager->ReportRtsFailed (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0));
1694 
1695  Ptr<QosTxop> qosTxop = DynamicCast<QosTxop> (m_currentTxop);
1696  if (qosTxop != 0)
1697  {
1699  }
1700  else
1701  {
1703  }
1704  m_currentTxop = 0;
1705 }
1706 
1707 void
1709 {
1710  NS_LOG_FUNCTION (this);
1711  NS_LOG_DEBUG ("normal ack timeout");
1715  Ptr<Txop> txop = m_currentTxop;
1716  m_currentTxop = 0;
1717  txop->MissedAck ();
1718 }
1719 
1720 void
1722 {
1723  NS_LOG_FUNCTION (this);
1724  NS_LOG_DEBUG ("block ack timeout");
1725  Ptr<Txop> txop = m_currentTxop;
1726  m_currentTxop = 0;
1727  txop->MissedBlockAck (m_currentPacket->GetNMpdus ());
1728 }
1729 
1730 void
1732 {
1733  NS_LOG_FUNCTION (this);
1734  /* send an RTS for this packet. */
1735  WifiMacHeader rts;
1736  rts.SetType (WIFI_MAC_CTL_RTS);
1737  rts.SetDsNotFrom ();
1738  rts.SetDsNotTo ();
1739  rts.SetNoRetry ();
1740  rts.SetNoMoreFragments ();
1741  rts.SetAddr1 (m_currentPacket->GetAddr1 ());
1742  rts.SetAddr2 (m_self);
1743  WifiTxVector rtsTxVector = GetRtsTxVector (*m_currentPacket->begin ());
1744  Time duration = Seconds (0);
1745 
1746  duration += GetSifs ();
1747  duration += GetCtsDuration (m_currentPacket->GetAddr1 (), rtsTxVector);
1748  duration += GetSifs ();
1749  duration += m_phy->CalculateTxDuration (m_currentPacket->GetSize (),
1751  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1752  if (m_txParams.HasNextPacket ())
1753  {
1756  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1757  }
1758  rts.SetDuration (duration);
1759 
1760  Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetPhyBand ());
1761  // After transmitting an RTS frame, the STA shall wait for a CTSTimeout interval with
1762  // a value of aSIFSTime + aSlotTime + aRxPHYStartDelay (IEEE 802.11-2016 sec. 10.3.2.7).
1763  // aRxPHYStartDelay equals the time to transmit the PHY header.
1764  Time timerDelay = txDuration + GetSifs () + GetSlotTime ()
1767  NotifyCtsTimeoutStartNow (timerDelay);
1769 
1770  ForwardDown (Create<const WifiPsdu> (Create<Packet> (), rts), rtsTxVector);
1771 }
1772 
1773 void
1775 {
1776  Time txDuration = m_phy->CalculateTxDuration (m_currentPacket->GetSize (), dataTxVector, m_phy->GetPhyBand ());
1777  if (m_txParams.MustWaitNormalAck () && !IsCfPeriod ())
1778  {
1779  // the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
1780  // at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
1781  // aRxPHYStartDelay equals the time to transmit the PHY header.
1782  WifiTxVector ackTxVector = GetAckTxVector (m_currentPacket->GetAddr1 (),
1783  dataTxVector.GetMode ());
1784  Time timerDelay = txDuration + GetSifs () + GetSlotTime ()
1787  NotifyAckTimeoutStartNow (timerDelay);
1789  }
1790  else if (m_txParams.MustWaitBlockAck ())
1791  {
1792  // the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
1793  // at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
1794  // aRxPHYStartDelay equals the time to transmit the PHY header.
1795  WifiTxVector blockAckTxVector = GetBlockAckTxVector (m_currentPacket->GetAddr1 (),
1796  dataTxVector.GetMode ());
1797  Time timerDelay = txDuration + GetSifs () + GetSlotTime ()
1798  + m_phy->CalculatePhyPreambleAndHeaderDuration (blockAckTxVector);
1800  NotifyAckTimeoutStartNow (timerDelay);
1802  }
1803  else if (m_txParams.HasNextPacket ())
1804  {
1806  Time delay = txDuration + GetSifs ();
1808  }
1809  else if (m_currentPacket->GetHeader (0).IsQosData () && m_currentTxop->IsQosTxop () &&
1811  {
1812  Time delay = txDuration + GetSifs ();
1814  }
1815  else
1816  {
1817  // since we do not expect any timer to be triggered.
1819  }
1820 }
1821 
1822 void
1824 {
1825  NS_LOG_FUNCTION (this);
1826  /* send this packet directly. No RTS is needed. */
1828 
1829  if (!IsCfPeriod ())
1830  {
1832  if (m_txParams.HasNextPacket ())
1833  {
1834  duration += GetSifs ();
1837  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1838  }
1839  m_currentPacket->SetDuration (duration);
1840  }
1841  else
1842  {
1843  if (m_currentPacket->GetHeader (0).IsCfEnd ())
1844  {
1845  m_currentPacket->GetHeader (0).SetRawDuration (0);
1846  }
1847  else
1848  {
1849  m_currentPacket->GetHeader (0).SetRawDuration (32768);
1850  }
1851  }
1852 
1853  if (!m_currentPacket->IsAggregate ())
1854  {
1856  {
1857  switch (m_currentPacket->GetHeader (0).GetType ())
1858  {
1859  case WIFI_MAC_DATA:
1860  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_CFACK, false);
1861  break;
1862  case WIFI_MAC_DATA_CFPOLL:
1863  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_CFACK_CFPOLL, false);
1864  break;
1865  case WIFI_MAC_DATA_NULL:
1866  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_NULL_CFACK, false);
1867  break;
1869  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_NULL_CFACK_CFPOLL, false);
1870  break;
1871  case WIFI_MAC_CTL_END:
1872  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_CTL_END_ACK, false);
1873  break;
1874  default:
1875  NS_ASSERT (false);
1876  break;
1877  }
1879  //Standard says that, for frames of type Data+CF-Ack, Data+CF-Poll+CF-Ack, and CF-Poll+CF-Ack,
1880  //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.
1881  //This ideally requires the rate manager to handle this case, but this requires to update all rate manager classes.
1882  //Instead, we simply fetch two TxVector and we select the one with the lowest data rate.
1883  //This should be later changed, at the latest once HCCA is implemented for HT/VHT/HE stations.
1884  WifiMacHeader tmpHdr = m_currentPacket->GetHeader (0);
1885  tmpHdr.SetAddr1 (m_cfAckInfo.address);
1886  WifiTxVector tmpTxVector = GetDataTxVector (Create<const WifiMacQueueItem> (m_currentPacket->GetPayload (0), tmpHdr));
1887  if (tmpTxVector.GetMode ().GetDataRate (tmpTxVector) < m_currentTxVector.GetMode ().GetDataRate (m_currentTxVector))
1888  {
1889  m_currentTxVector = tmpTxVector;
1890  }
1891  m_cfAckInfo.appendCfAck = false;
1893  }
1894  }
1896  {
1897  Ptr<QosTxop> qosTxop = DynamicCast<QosTxop> (m_currentTxop);
1898  NS_ASSERT (qosTxop != 0);
1899  auto bar = qosTxop->PrepareBlockAckRequest (m_currentPacket->GetAddr1 (), *m_currentPacket->GetTids ().begin ());
1900  qosTxop->ScheduleBar (bar);
1901  }
1903 }
1904 
1905 bool
1906 MacLow::IsNavZero (void) const
1907 {
1909 }
1910 
1911 void
1913 {
1914  WifiMacHeader cts;
1915  cts.SetType (WIFI_MAC_CTL_CTS);
1916  cts.SetDsNotFrom ();
1917  cts.SetDsNotTo ();
1918  cts.SetNoMoreFragments ();
1919  cts.SetNoRetry ();
1920  cts.SetAddr1 (m_self);
1921 
1922  WifiTxVector ctsTxVector = GetRtsTxVector (*m_currentPacket->begin ());
1923  Time duration = Seconds (0);
1924 
1925  duration += GetSifs ();
1926  duration += m_phy->CalculateTxDuration (m_currentPacket->GetSize (),
1928  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1929  if (m_txParams.HasNextPacket ())
1930  {
1931  duration += GetSifs ();
1934  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1935  }
1936 
1937  cts.SetDuration (duration);
1938 
1939  ForwardDown (Create<const WifiPsdu> (Create<Packet> (), cts), ctsTxVector);
1940 
1941  Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetPhyBand ());
1942  txDuration += GetSifs ();
1944 
1945  m_sendDataEvent = Simulator::Schedule (txDuration,
1946  &MacLow::SendDataAfterCts, this,
1947  duration);
1948 }
1949 
1950 void
1951 MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
1952 {
1953  NS_LOG_FUNCTION (this << source << duration << rtsTxVector.GetMode () << rtsSnr);
1954  /* send a CTS when you receive a RTS
1955  * right after SIFS.
1956  */
1957  WifiTxVector ctsTxVector = GetCtsTxVector (source, rtsTxVector.GetMode ());
1958  WifiMacHeader cts;
1959  cts.SetType (WIFI_MAC_CTL_CTS);
1960  cts.SetDsNotFrom ();
1961  cts.SetDsNotTo ();
1962  cts.SetNoMoreFragments ();
1963  cts.SetNoRetry ();
1964  cts.SetAddr1 (source);
1965  duration -= GetCtsDuration (source, rtsTxVector);
1966  duration -= GetSifs ();
1967  NS_ASSERT (duration.IsPositive ());
1968  cts.SetDuration (duration);
1969 
1970  Ptr<Packet> packet = Create<Packet> ();
1971 
1972  SnrTag tag;
1973  tag.Set (rtsSnr);
1974  packet->AddPacketTag (tag);
1975 
1976  //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1977  ForwardDown (Create<const WifiPsdu> (packet, cts), ctsTxVector);
1978 }
1979 
1980 void
1982 {
1983  NS_LOG_FUNCTION (this);
1984  /* send the third step in a
1985  * RTS/CTS/Data/Ack handshake
1986  */
1987  NS_ASSERT (m_currentPacket != 0);
1988 
1990  Time newDuration = GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1991  if (m_txParams.HasNextPacket ())
1992  {
1993  newDuration += GetSifs ();
1995  newDuration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1996  }
1997 
1999  duration -= txDuration;
2000  duration -= GetSifs ();
2001 
2002  duration = std::max (duration, newDuration);
2003  NS_ASSERT (duration.IsPositive ());
2004  m_currentPacket->SetDuration (duration);
2006  {
2007  Ptr<QosTxop> qosTxop = DynamicCast<QosTxop> (m_currentTxop);
2008  NS_ASSERT (qosTxop != 0);
2009  auto bar = qosTxop->PrepareBlockAckRequest (m_currentPacket->GetAddr1 (), *m_currentPacket->GetTids ().begin ());
2010  qosTxop->ScheduleBar (bar);
2011  }
2013 }
2014 
2015 void
2017 {
2018  NS_LOG_FUNCTION (this);
2020 }
2021 
2022 void
2024 {
2025  NS_LOG_FUNCTION (this);
2027 }
2028 
2029 void
2031 {
2032  NS_LOG_FUNCTION (this);
2033  if (m_currentPacket->GetHeader (0).IsBeacon () && m_stationManager->GetPcfSupported ())
2034  {
2036  }
2037  if (!m_cfAckInfo.expectCfAck)
2038  {
2039  Ptr<Txop> txop = m_currentTxop;
2040  txop->EndTxNoAck ();
2041  }
2042  if (!IsCfPeriod ())
2043  {
2044  m_currentTxop = 0;
2045  }
2046 }
2047 
2048 void
2049 MacLow::SendAckAfterData (Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
2050 {
2051  NS_LOG_FUNCTION (this);
2052  // send an Ack, after SIFS, when you receive a packet
2053  WifiTxVector ackTxVector = GetAckTxVector (source, dataTxMode);
2054  WifiMacHeader ack;
2055  ack.SetType (WIFI_MAC_CTL_ACK);
2056  ack.SetDsNotFrom ();
2057  ack.SetDsNotTo ();
2058  ack.SetNoRetry ();
2059  ack.SetNoMoreFragments ();
2060  ack.SetAddr1 (source);
2061  // 802.11-2012, Section 8.3.1.4: Duration/ID is received duration value
2062  // minus the time to transmit the Ack frame and its SIFS interval
2063  duration -= GetAckDuration (ackTxVector);
2064  duration -= GetSifs ();
2065  NS_ASSERT_MSG (duration.IsPositive (), "Please provide test case to maintainers if this assert is hit.");
2066  ack.SetDuration (duration);
2067 
2068  Ptr<Packet> packet = Create<Packet> ();
2069 
2070  SnrTag tag;
2071  tag.Set (dataSnr);
2072  packet->AddPacketTag (tag);
2073 
2074  //Ack should always use non-HT PPDU (HT PPDU cases not supported yet)
2075  ForwardDown (Create<const WifiPsdu> (packet, ack), ackTxVector);
2076 }
2077 
2078 bool
2080 {
2081  const WifiMacHeader& hdr = mpdu->GetHeader ();
2082 
2086  {
2087  Mac48Address originator = hdr.GetAddr2 ();
2088  uint8_t tid = 0;
2089  if (hdr.IsQosData ())
2090  {
2091  tid = hdr.GetQosTid ();
2092  }
2093  uint16_t seqNumber = hdr.GetSequenceNumber ();
2094  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2095  if (it != m_bAckAgreements.end ())
2096  {
2097  //Implement HT immediate BlockAck support for HT Delayed BlockAck is not added yet
2098  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), seqNumber))
2099  {
2100  StoreMpduIfNeeded (mpdu);
2101  if (!IsInWindow (hdr.GetSequenceNumber (), (*it).second.first.GetStartingSequence (), (*it).second.first.GetBufferSize ()))
2102  {
2103  uint16_t delta = (seqNumber - (*it).second.first.GetWinEnd () + 4096) % 4096;
2104  NS_ASSERT (delta > 0);
2105  uint16_t bufferSize = (*it).second.first.GetBufferSize ();
2106  uint16_t startingSeq = (seqNumber - bufferSize + 1 + 4096) % 4096;
2107  (*it).second.first.SetStartingSequence (startingSeq);
2108  RxCompleteBufferedPacketsWithSmallerSequence ((*it).second.first.GetStartingSequenceControl (), originator, tid);
2109  }
2110  RxCompleteBufferedPacketsUntilFirstLost (originator, tid); //forwards up packets starting from winstart and set winstart to last +1
2111  }
2112  return true;
2113  }
2114  return false;
2115  }
2116  return StoreMpduIfNeeded (mpdu);
2117 }
2118 
2119 bool
2121 {
2122  const WifiMacHeader& hdr = mpdu->GetHeader ();
2123 
2124  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2125  if (it != m_bAckAgreements.end ())
2126  {
2127  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2128  uint32_t mappedSeqControl = QosUtilsMapSeqControlToUniqueInteger (hdr.GetSequenceControl (), endSequence);
2129 
2130  BufferedPacketI i = (*it).second.second.begin ();
2131  for (; i != (*it).second.second.end ()
2132  && QosUtilsMapSeqControlToUniqueInteger ((*i)->GetHeader ().GetSequenceControl (), endSequence) < mappedSeqControl; i++)
2133  {
2134  }
2135  (*it).second.second.insert (i, mpdu);
2136 
2137  //Update block ack cache
2138  BlockAckCachesI j = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2139  NS_ASSERT (j != m_bAckCaches.end ());
2140  (*j).second.UpdateWithMpdu (&hdr);
2141  return true;
2142  }
2143  return false;
2144 }
2145 
2146 void
2148  uint16_t startingSeq)
2149 {
2150  NS_LOG_FUNCTION (this);
2151  uint8_t tid = respHdr->GetTid ();
2152  BlockAckAgreement agreement (originator, tid);
2153  if (respHdr->IsImmediateBlockAck ())
2154  {
2155  agreement.SetImmediateBlockAck ();
2156  }
2157  else
2158  {
2159  agreement.SetDelayedBlockAck ();
2160  }
2161  agreement.SetAmsduSupport (respHdr->IsAmsduSupported ());
2162  agreement.SetBufferSize (respHdr->GetBufferSize () + 1);
2163  agreement.SetTimeout (respHdr->GetTimeout ());
2164  agreement.SetStartingSequence (startingSeq);
2165 
2166  std::list<Ptr<WifiMacQueueItem>> buffer (0);
2167  AgreementKey key (originator, respHdr->GetTid ());
2168  AgreementValue value (agreement, buffer);
2169  m_bAckAgreements.insert (std::make_pair (key, value));
2170 
2171  BlockAckCache cache;
2172  cache.Init (startingSeq, respHdr->GetBufferSize () + 1);
2173  m_bAckCaches.insert (std::make_pair (key, cache));
2174 
2175  if (respHdr->GetTimeout () != 0)
2176  {
2177  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, respHdr->GetTid ()));
2178  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2179 
2180  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2181 
2182  it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
2184  m_edca[ac], originator, tid, false);
2185  }
2186 }
2187 
2188 void
2190 {
2191  NS_LOG_FUNCTION (this);
2192  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2193  if (it != m_bAckAgreements.end ())
2194  {
2195  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (), originator, tid);
2196  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2197  m_bAckAgreements.erase (it);
2198  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2199  NS_ASSERT (i != m_bAckCaches.end ());
2200  m_bAckCaches.erase (i);
2201  }
2202 }
2203 
2204 void
2206 {
2207  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2208  if (it != m_bAckAgreements.end ())
2209  {
2210  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2211  uint32_t mappedStart = QosUtilsMapSeqControlToUniqueInteger (seq, endSequence);
2212  BufferedPacketI last = (*it).second.second.begin ();
2213  uint16_t guard = 0;
2214  if (last != (*it).second.second.end ())
2215  {
2216  guard = (*(*it).second.second.begin ())->GetHeader ().GetSequenceControl ();
2217  }
2218  BufferedPacketI i = (*it).second.second.begin ();
2219  for (; i != (*it).second.second.end ()
2220  && QosUtilsMapSeqControlToUniqueInteger ((*i)->GetHeader ().GetSequenceControl (), endSequence) < mappedStart; )
2221  {
2222  if (guard == (*i)->GetHeader ().GetSequenceControl ())
2223  {
2224  if (!(*i)->GetHeader ().IsMoreFragments ())
2225  {
2226  while (last != i)
2227  {
2228  m_rxCallback (*last);
2229  last++;
2230  }
2231  m_rxCallback (*last);
2232  last++;
2233  /* go to next packet */
2234  while (i != (*it).second.second.end () && guard == (*i)->GetHeader ().GetSequenceControl ())
2235  {
2236  i++;
2237  }
2238  if (i != (*it).second.second.end ())
2239  {
2240  guard = (*i)->GetHeader ().GetSequenceControl ();
2241  last = i;
2242  }
2243  }
2244  else
2245  {
2246  guard++;
2247  }
2248  }
2249  else
2250  {
2251  /* go to next packet */
2252  while (i != (*it).second.second.end () && guard == (*i)->GetHeader ().GetSequenceControl ())
2253  {
2254  i++;
2255  }
2256  if (i != (*it).second.second.end ())
2257  {
2258  guard = (*i)->GetHeader ().GetSequenceControl ();
2259  last = i;
2260  }
2261  }
2262  }
2263  (*it).second.second.erase ((*it).second.second.begin (), i);
2264  }
2265 }
2266 
2267 void
2269 {
2270  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2271  if (it != m_bAckAgreements.end ())
2272  {
2273  uint16_t guard = (*it).second.first.GetStartingSequenceControl ();
2274  BufferedPacketI lastComplete = (*it).second.second.begin ();
2275  BufferedPacketI i = (*it).second.second.begin ();
2276  for (; i != (*it).second.second.end () && guard == (*i)->GetHeader ().GetSequenceControl (); i++)
2277  {
2278  if (!(*i)->GetHeader ().IsMoreFragments ())
2279  {
2280  while (lastComplete != i)
2281  {
2282  m_rxCallback (*lastComplete);
2283  lastComplete++;
2284  }
2285  m_rxCallback (*lastComplete);
2286  lastComplete++;
2287  }
2288  guard = (*i)->GetHeader ().IsMoreFragments () ? (guard + 1) : ((guard + 16) & 0xfff0);
2289  }
2290  (*it).second.first.SetStartingSequenceControl (guard);
2291  /* All packets already forwarded to WifiMac must be removed from buffer:
2292  [begin (), lastComplete) */
2293  (*it).second.second.erase ((*it).second.second.begin (), lastComplete);
2294  }
2295 }
2296 
2297 void
2298 MacLow::SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate,
2299  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2300 {
2301  NS_LOG_FUNCTION (this);
2302  Ptr<Packet> packet = Create<Packet> ();
2303  packet->AddHeader (*blockAck);
2304 
2305  WifiMacHeader hdr;
2307  hdr.SetAddr1 (originator);
2308  hdr.SetAddr2 (GetAddress ());
2309  hdr.SetDsNotFrom ();
2310  hdr.SetDsNotTo ();
2311  hdr.SetNoRetry ();
2312  hdr.SetNoMoreFragments ();
2313 
2314  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (originator, blockAckReqTxMode);
2315 
2316  if (immediate)
2317  {
2319  duration -= GetSifs ();
2320  duration -= GetBlockAckDuration (blockAckReqTxVector, blockAck->GetType ());
2321  }
2322  else
2323  {
2324  m_txParams.EnableAck ();
2325  duration += GetSifs ();
2326  duration += GetAckDuration (originator, blockAckReqTxVector);
2327  }
2329 
2330  if (!immediate)
2331  {
2332  StartDataTxTimers (blockAckReqTxVector);
2333  }
2334 
2335  NS_ASSERT (duration.IsPositive ());
2336  hdr.SetDuration (duration);
2337  //here should be present a control about immediate or delayed BlockAck
2338  //for now we assume immediate
2339  SnrTag tag;
2340  tag.Set (rxSnr);
2341  packet->AddPacketTag (tag);
2342  ForwardDown (Create<const WifiPsdu> (packet, hdr), blockAckReqTxVector);
2343 }
2344 
2345 void
2346 MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector, double rxSnr)
2347 {
2348  NS_LOG_FUNCTION (this);
2349  if (!m_phy->IsStateTx () && !m_phy->IsStateRx ())
2350  {
2351  NS_LOG_FUNCTION (this << +tid << originator << duration.As (Time::S) << blockAckReqTxVector << rxSnr);
2352  CtrlBAckResponseHeader blockAck;
2353  uint16_t seqNumber = 0;
2354  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2355  NS_ASSERT (i != m_bAckCaches.end ());
2356  seqNumber = (*i).second.GetWinStart ();
2357 
2358  bool immediate = true;
2359  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2360  blockAck.SetStartingSequence (seqNumber);
2361  blockAck.SetTidInfo (tid);
2362  immediate = (*it).second.first.IsImmediateBlockAck ();
2363  if ((*it).second.first.GetBufferSize () > 64)
2364  {
2365  blockAck.SetType (EXTENDED_COMPRESSED_BLOCK_ACK);
2366  }
2367  else
2368  {
2369  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2370  }
2371  NS_LOG_DEBUG ("Got Implicit block Ack Req with seq " << seqNumber);
2372  (*i).second.FillBlockAckBitmap (&blockAck);
2373 
2374  WifiTxVector blockAckTxVector = GetBlockAckTxVector (originator, blockAckReqTxVector.GetMode ());
2375 
2376  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckTxVector.GetMode (), rxSnr);
2377  }
2378  else
2379  {
2380  NS_LOG_DEBUG ("Skip block ack response!");
2381  }
2382 }
2383 
2384 void
2386  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2387 {
2388  NS_LOG_FUNCTION (this);
2389  CtrlBAckResponseHeader blockAck;
2390  uint8_t tid = 0;
2391  bool immediate = false;
2392  if (!reqHdr.IsMultiTid ())
2393  {
2394  tid = reqHdr.GetTidInfo ();
2395  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2396  if (it != m_bAckAgreements.end ())
2397  {
2398  blockAck.SetStartingSequence (reqHdr.GetStartingSequence ());
2399  blockAck.SetTidInfo (tid);
2400  immediate = (*it).second.first.IsImmediateBlockAck ();
2401  if (reqHdr.IsBasic ())
2402  {
2403  blockAck.SetType (BASIC_BLOCK_ACK);
2404  }
2405  else if (reqHdr.IsCompressed ())
2406  {
2407  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2408  }
2409  else if (reqHdr.IsExtendedCompressed ())
2410  {
2412  }
2413  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2414  NS_ASSERT (i != m_bAckCaches.end ());
2415  (*i).second.FillBlockAckBitmap (&blockAck);
2416  NS_LOG_DEBUG ("Got block Ack Req with seq " << reqHdr.GetStartingSequence ());
2417 
2421  {
2422  /* All packets with smaller sequence than starting sequence control must be passed up to WifiMac
2423  * See 9.10.3 in IEEE 802.11e standard.
2424  */
2426  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2427  }
2428  else
2429  {
2430  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), reqHdr.GetStartingSequence ()))
2431  {
2432  (*it).second.first.SetStartingSequence (reqHdr.GetStartingSequence ());
2434  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2435  }
2436  }
2437  }
2438  else
2439  {
2440  NS_LOG_DEBUG ("there's not a valid block ack agreement with " << originator);
2441  }
2442  }
2443  else
2444  {
2445  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2446  }
2447  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode, rxSnr);
2448 }
2449 
2450 void
2452 {
2453  if (agreement.GetTimeout () != 0)
2454  {
2455  NS_ASSERT (agreement.m_inactivityEvent.IsRunning ());
2456  agreement.m_inactivityEvent.Cancel ();
2457  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2458  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2461  m_edca[ac], agreement.GetPeer (),
2462  agreement.GetTid (), false);
2463  }
2464 }
2465 
2466 void
2468 {
2469  m_edca.insert (std::make_pair (ac, edca));
2470 }
2471 
2472 void
2473 MacLow::DeaggregateAmpduAndReceive (Ptr<WifiPsdu> psdu, double rxSnr, WifiTxVector txVector, std::vector<bool> statusPerMpdu)
2474 {
2475  NS_LOG_FUNCTION (this);
2476  bool normalAck = false;
2477  bool ampduSubframe = txVector.IsAggregation (); //flag indicating the packet belongs to an A-MPDU and is not a VHT/HE single MPDU
2478  //statusPerMpdu is empty for intermediate MPDU forwarding.
2479  //This function is called also once the PPDU has been fully received by the PHY,
2480  //in that case statusPerMpdu carries the information about the received MPDUs.
2481  if (ampduSubframe && !statusPerMpdu.empty ())
2482  {
2483  //We are here if a S-MPDU is received or if all MPDUs of an A-MPDU have been
2484  //received (but have been already forwarded up, so ReceiveOk won't be called)
2485  NS_ASSERT (psdu->IsAggregate ());
2486  ampduSubframe = true;
2487  auto n = psdu->begin ();
2488  auto status = statusPerMpdu.begin ();
2489  NS_ABORT_MSG_IF (psdu->GetNMpdus () != statusPerMpdu.size (), "Should have one receive status per MPDU");
2490 
2491  WifiMacHeader firsthdr = (*n)->GetHeader ();
2492  if (firsthdr.GetAddr1 () == m_self)
2493  {
2494  //Iterate over all MPDUs and notify reception only if status OK
2495  for (; n != psdu->end (); ++n, ++status)
2496  {
2497  firsthdr = (*n)->GetHeader ();
2498  NS_ABORT_MSG_IF (firsthdr.GetAddr1 () != m_self, "All MPDUs of A-MPDU should have the same destination address");
2499  if (*status) //PER and thus CRC check succeeded
2500  {
2501  if (psdu->IsSingle ())
2502  {
2503  //If the MPDU is sent as a VHT/HE single MPDU (EOF=1 in A-MPDU subframe header), then the responder sends an Ack.
2504  NS_LOG_DEBUG ("Receive S-MPDU");
2505  ampduSubframe = false;
2506  }
2507  else if (!m_sendAckEvent.IsRunning () && firsthdr.IsQosAck ()) // Implicit BAR Ack Policy
2508  {
2511  firsthdr.GetQosTid (),
2512  firsthdr.GetAddr2 (),
2513  firsthdr.GetDuration (),
2514  txVector, rxSnr);
2515  }
2516 
2517  if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ())
2518  {
2519  ReceiveOk ((*n), rxSnr, txVector, ampduSubframe);
2520  }
2521  else if (firsthdr.IsData () || firsthdr.IsQosData ())
2522  {
2523  NS_LOG_DEBUG ("Deaggregate packet from " << firsthdr.GetAddr2 () << " with sequence=" << firsthdr.GetSequenceNumber ());
2524  if (psdu->IsSingle ())
2525  {
2526  ReceiveOk ((*n), rxSnr, txVector, ampduSubframe);
2527  }
2528  if (firsthdr.IsQosAck ())
2529  {
2530  NS_LOG_DEBUG ("Normal Ack");
2531  normalAck = true;
2532  }
2533  }
2534  else
2535  {
2536  NS_FATAL_ERROR ("Received A-MPDU with invalid first MPDU type");
2537  }
2538 
2539  if (!psdu->IsSingle ())
2540  {
2541  if (normalAck)
2542  {
2543  //send BlockAck
2544  if (firsthdr.IsBlockAckReq ())
2545  {
2546  NS_FATAL_ERROR ("Sending a BlockAckReq with QosPolicy equal to Normal Ack");
2547  }
2548  uint8_t tid = firsthdr.GetQosTid ();
2549  AgreementsI it = m_bAckAgreements.find (std::make_pair (firsthdr.GetAddr2 (), tid));
2550  if (it != m_bAckAgreements.end ())
2551  {
2552  /* See section 11.5.3 in IEEE 802.11 for the definition of this timer */
2553  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
2554  NS_LOG_DEBUG ("rx A-MPDU/sendImmediateBlockAck from=" << firsthdr.GetAddr2 ());
2556  }
2557  else
2558  {
2559  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
2560  }
2561  }
2562  }
2563  }
2564  }
2565  }
2566  }
2567  else
2568  {
2569  /* An MPDU has been received */
2570  NS_ASSERT (!psdu->IsAggregate ());
2571  ReceiveOk ((*psdu->begin ()), rxSnr, txVector, ampduSubframe);
2572  }
2573 }
2574 
2575 Time
2577 {
2578  NS_LOG_FUNCTION (this);
2580  NS_ASSERT (remainingCfpDuration.IsPositive ());
2581  return remainingCfpDuration;
2582 }
2583 
2584 bool
2586 {
2588 }
2589 
2590 bool
2592 {
2593  NS_LOG_FUNCTION (this);
2594  if (!IsCfPeriod ())
2595  {
2596  return false;
2597  }
2598  NS_ASSERT (GetRemainingCfpDuration ().IsPositive ());
2599  WifiMacHeader hdr;
2600  hdr.SetType (WIFI_MAC_DATA);
2601  WifiMacTrailer fcs;
2602  uint32_t maxMacFrameSize = MAX_MSDU_SIZE + hdr.GetSerializedSize () + fcs.GetSerializedSize ();
2603  Time nextTransmission = 2 * m_phy->CalculateTxDuration (maxMacFrameSize, m_currentTxVector, m_phy->GetPhyBand ()) + 3 * GetSifs () + m_phy->CalculateTxDuration (GetCfEndSize (), m_currentTxVector, m_phy->GetPhyBand ());
2604  return ((GetRemainingCfpDuration () - nextTransmission).IsPositive ());
2605 }
2606 
2607 } //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:2023
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
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:429
bool IsStateOff(void) const
Definition: wifi-phy.cc:4569
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.
bool IsSingle(void) const
Return true if the PSDU is an S-MPDU.
Definition: wifi-psdu.cc:75
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:2451
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:1437
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:4314
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:2385
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
bool ReceiveMpdu(Ptr< WifiMacQueueItem > mpdu)
Definition: mac-low.cc:2079
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:274
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:1536
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:1426
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:1548
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:589
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:1459
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:695
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:1207
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:1906
void NotifyOffNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:747
double ToDouble(enum Unit unit) const
Get the Time value expressed in a particular unit.
Definition: nstime.h:530
void NotifySleepNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:732
void NotifyNav(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Notify NAV function.
Definition: mac-low.cc:1491
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:333
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:813
uint16_t GetBufferSize(void) const
Return the buffer size.
VHT PHY (Clause 22)
Definition: wifi-mode.h:62
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...
WifiTxVector GetRtsTxVector(Ptr< const WifiMacQueueItem > item) const
Return a TXVECTOR for the RTS frame given the destination.
Definition: mac-low.cc:1195
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:99
WifiMode GetControlAnswerMode(WifiMode reqMode) const
Get control answer mode function.
Definition: mac-low.cc:1235
void NotifyAckTimeoutResetNow(void)
Notify ChannelAccessManager that Ack timer should be reset.
Definition: mac-low.cc:1575
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:1476
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:451
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:1708
uint32_t GetSize(void) const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:260
phy
Definition: third.py:93
BlockAckCaches m_bAckCaches
block ack caches
Definition: mac-low.h:900
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode...
uint16_t GetChannelWidth(void) const
Definition: wifi-phy.cc:1516
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:4308
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:2189
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:1188
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:1912
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:2049
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
#define max(a, b)
Definition: 80211b.c:43
void CreateBlockAckAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address originator, uint16_t startingSeq)
Definition: mac-low.cc:2147
bool IsZero(void) const
Exactly equivalent to t == 0.
Definition: nstime.h:301
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:1313
receive notifications about PHY events.
void CtsTimeout(void)
Event handler when CTS timeout occurs.
Definition: mac-low.cc:1686
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:2473
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:2030
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:2346
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:2585
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:2120
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.
HT PHY (Clause 20)
Definition: wifi-mode.h:60
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:1981
void RegisterEdcaForAc(AcIndex ac, Ptr< QosTxop > edca)
Definition: mac-low.cc:2467
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:1201
virtual bool IsQosTxop() const
Check for QoS TXOP.
Definition: txop.cc:861
void NotifySwitchingStartNow(Time duration)
Definition: mac-low.cc:716
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:480
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:1393
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.
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:1377
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
void BlockAckTimeout(void)
Event handler when BlockAck timeout occurs.
Definition: mac-low.cc:1721
void NotifyCtsTimeoutStartNow(Time duration)
Notify ChannelAccessManager that CTS timer should be started for the given duration.
Definition: mac-low.cc:1584
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.
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:319
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Time GetRemainingCfpDuration(void) const
Definition: mac-low.cc:2576
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:575
void StartDataTxTimers(WifiTxVector dataTxVector)
Start a Data timer by scheduling appropriate Ack timeout.
Definition: mac-low.cc:1774
#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:2298
Time GetAckDuration(WifiTxVector ackTxVector) const
Return the time required to transmit the Ack (including preamble and FCS).
Definition: mac-low.cc:1158
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:974
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:2205
void SendCtsAfterRts(Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
Send CTS after receiving RTS.
Definition: mac-low.cc:1951
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:1175
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:4296
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:583
WifiMode GetMode(uint8_t mode) const
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
Definition: wifi-phy.cc:4302
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:4551
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:1431
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:38
#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:762
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:1409
Time GetSifs(void) const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:950
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:1566
bool CanTransmitNextCfFrame(void) const
This function decides if a CF frame can be transmitted in the current CFP.
Definition: mac-low.cc:2591
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:317
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:1289
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:962
std::vector< Ptr< WifiMacQueueItem > >::const_iterator begin(void) const
Return a const iterator to the first MPDU.
Definition: wifi-psdu.cc:325
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:1165
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:2707
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:759
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:1823
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:1305
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:1136
void ForwardDown(Ptr< const WifiPsdu > psdu, WifiTxVector txVector)
Forward a PSDU down to WifiPhy for transmission.
Definition: mac-low.cc:1602
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:2016
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
static Time CalculateTxDuration(uint32_t size, WifiTxVector txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:2546
void CfPollTimeout(void)
Event handler when CF-Poll timeout occurs.
Definition: mac-low.cc:1668
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:1593
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:1425
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:595
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:4545
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:64
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:127
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:309
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:1731
BlockAckType
The different block ack policies.
bool IsAggregate(void) const
Return true if the PSDU is an S-MPDU or A-MPDU.
Definition: wifi-psdu.cc:81
static Time CalculatePhyPreambleAndHeaderDuration(WifiTxVector txVector)
Definition: wifi-phy.cc:2532
void RxCompleteBufferedPacketsUntilFirstLost(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2268
Time GetTxopLimit(void) const
Return the TXOP limit.
Definition: txop.cc:303