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_ackTimeout = ackTimeout;
334 }
335 
336 void
338 {
339  m_basicBlockAckTimeout = blockAckTimeout;
340 }
341 
342 void
344 {
345  m_compressedBlockAckTimeout = blockAckTimeout;
346 }
347 
348 void
350 {
351  m_ctsToSelfSupported = enable;
352 }
353 
354 bool
356 {
357  return m_ctsToSelfSupported;
358 }
359 
360 void
362 {
363  m_sifs = sifs;
364 }
365 
366 void
368 {
369  m_slotTime = slotTime;
370 }
371 
372 void
374 {
375  m_pifs = pifs;
376 }
377 
378 void
380 {
381  m_rifs = rifs;
382 }
383 
384 void
386 {
387  m_beaconInterval = interval;
388 }
389 
390 void
392 {
393  m_cfpMaxDuration = cfpMaxDuration;
394 }
395 
396 void
398 {
399  m_bssid = bssid;
400 }
401 
402 void
404 {
405  m_promisc = true;
406 }
407 
409 MacLow::GetAddress (void) const
410 {
411  return m_self;
412 }
413 
414 Time
416 {
417  return m_ackTimeout;
418 }
419 
420 Time
422 {
423  return m_basicBlockAckTimeout;
424 }
425 
426 Time
428 {
430 }
431 
432 Time
433 MacLow::GetSifs (void) const
434 {
435  return m_sifs;
436 }
437 
438 Time
439 MacLow::GetRifs (void) const
440 {
441  return m_rifs;
442 }
443 
444 Time
446 {
447  return m_slotTime;
448 }
449 
450 Time
451 MacLow::GetPifs (void) const
452 {
453  return m_pifs;
454 }
455 
457 MacLow::GetBssid (void) const
458 {
459  return m_bssid;
460 }
461 
462 Time
464 {
465  return m_beaconInterval;
466 }
467 
468 Time
470 {
471  return m_cfpMaxDuration;
472 }
473 
474 bool
475 MacLow::IsPromisc (void) const
476 {
477  return m_promisc;
478 }
479 
480 void
482 {
483  m_rxCallback = callback;
484 }
485 
486 void
488 {
489  m_channelAccessManagers.push_back (channelAccessManager);
490 }
491 
492 void
495  Ptr<Txop> txop)
496 {
497  NS_LOG_FUNCTION (this << *mpdu << params << txop);
499  if (m_phy->IsStateOff ())
500  {
501  NS_LOG_DEBUG ("Cannot start TX because device is OFF");
502  return;
503  }
504  /* m_currentPacket is not NULL because someone started
505  * a transmission and was interrupted before one of:
506  * - ctsTimeout
507  * - sendDataAfterCTS
508  * expired. This means that one of these timers is still
509  * running. They are all cancelled below anyway by the
510  * call to CancelAllEvents (because of at least one
511  * of these two timers) which will trigger a call to the
512  * previous listener's cancel method.
513  *
514  * This typically happens because the high-priority
515  * QapScheduler has taken access to the channel from
516  * one of the EDCA of the QAP.
517  */
518  m_currentPacket = Create<WifiPsdu> (mpdu, false);
519  const WifiMacHeader& hdr = mpdu->GetHeader ();
520  CancelAllEvents ();
521  m_currentTxop = txop;
522  m_txParams = params;
523  if (hdr.IsCtl ())
524  {
526  }
527  else
528  {
530  }
531 
532  /* The packet received by this function can be any of the following:
533  * (a) a management frame dequeued from the Txop
534  * (b) a non-QoS data frame dequeued from the Txop
535  * (c) a non-broadcast QoS Data frame peeked or dequeued from a QosTxop
536  * (d) a broadcast QoS data or DELBA Request frame dequeued from a QosTxop
537  * (e) a BlockAckReq or ADDBA Request frame
538  * (f) a fragment of non-QoS/QoS Data frame dequeued from the Txop/QosTxop
539  */
540  if (hdr.IsQosData () && !hdr.GetAddr1 ().IsBroadcast ()
541  && !hdr.IsMoreFragments () && hdr.GetFragmentNumber () == 0)
542  {
543  // We get here if the received packet is a non-broadcast QoS data frame
544  uint8_t tid = hdr.GetQosTid ();
545  Ptr<QosTxop> qosTxop = m_edca.find (QosUtilsMapTidToAc (tid))->second;
546 
547  // if a TXOP limit exists, compute the remaining TXOP duration
548  Time txopLimit = Time::Min ();
550  {
552  NS_ASSERT (txopLimit.IsPositive ());
553  }
554 
555  // QosTxop may send us a peeked frame
556  Ptr<const WifiMacQueueItem> tmp = qosTxop->PeekNextFrame ();
557  bool isPeeked = (tmp != 0 && tmp->GetPacket () == mpdu->GetPacket ());
558 
559  Ptr<WifiMacQueueItem> newMpdu;
560  // If the frame has been peeked, dequeue it if it meets the size and duration constraints
561  if (isPeeked)
562  {
563  newMpdu = qosTxop->DequeuePeekedFrame (mpdu, m_currentTxVector, true, 0, txopLimit);
564  }
565  else if (IsWithinSizeAndTimeLimits (mpdu, m_currentTxVector, 0, txopLimit))
566  {
567  newMpdu = mpdu;
568  }
569 
570  if (newMpdu == 0)
571  {
572  // if the frame has been dequeued, then there is no BA agreement with the
573  // receiver (otherwise the frame would have been peeked). Hence, the frame
574  // has been sent under Normal Ack policy, not acknowledged and now retransmitted.
575  // If we cannot send it now, let the QosTxop retransmit it again.
576  // If the frame has been just peeked, reset the current packet at QosTxop.
577  if (isPeeked)
578  {
579  qosTxop->UpdateCurrentPacket (Create<WifiMacQueueItem> (nullptr, WifiMacHeader ()));
580  }
581  return;
582  }
583  // Update the current packet at QosTxop, given that A-MSDU aggregation may have
584  // been performed on the peeked frame
585  qosTxop->UpdateCurrentPacket (newMpdu);
586 
587  //Perform MPDU aggregation if possible
588  std::vector<Ptr<WifiMacQueueItem>> mpduList;
589  if (m_mpduAggregator != 0)
590  {
591  mpduList = m_mpduAggregator->GetNextAmpdu (newMpdu, m_currentTxVector, txopLimit);
592  }
593 
594  if (mpduList.size () > 1)
595  {
596  m_currentPacket = Create<WifiPsdu> (mpduList);
597 
598  NS_LOG_DEBUG ("tx unicast A-MPDU containing " << mpduList.size () << " MPDUs");
599  qosTxop->SetAmpduExist (hdr.GetAddr1 (), true);
600  }
603  {
604  // VHT/HE single MPDU
605  m_currentPacket = Create<WifiPsdu> (newMpdu, true);
606 
607  NS_LOG_DEBUG ("tx unicast S-MPDU with sequence number " << hdr.GetSequenceNumber ());
608  qosTxop->SetAmpduExist (hdr.GetAddr1 (), true);
609  }
610  else // HT
611  {
612  m_currentPacket = Create<WifiPsdu> (newMpdu, false);
613  }
614 
615  // A QoS Txop must have an installed ack policy selector
616  NS_ASSERT (qosTxop->GetAckPolicySelector () != 0);
617  qosTxop->GetAckPolicySelector ()->UpdateTxParams (m_currentPacket, m_txParams);
618  qosTxop->GetAckPolicySelector ()->SetAckPolicy (m_currentPacket, m_txParams);
619  }
620 
621  NS_LOG_DEBUG ("startTx size=" << m_currentPacket->GetSize () <<
622  ", to=" << m_currentPacket->GetAddr1 () << ", txop=" << m_currentTxop);
623 
624  if (m_txParams.MustSendRts ())
625  {
626  SendRtsForPacket ();
627  }
628  else
629  {
631  {
632  SendCtsToSelf ();
633  }
634  else
635  {
636  SendDataPacket ();
637  }
638  }
639 
640  /* When this method completes, either we have taken ownership of the medium or the device switched off in the meantime. */
642 }
643 
644 bool
646 {
647  WifiTxVector dataTxVector = GetDataTxVector (*m_currentPacket->begin ());
648  return m_stationManager->NeedCtsToSelf (dataTxVector);
649 }
650 
651 bool
653  uint32_t ampduSize, Time ppduDurationLimit)
654 {
655  NS_ASSERT (mpdu != 0 && mpdu->GetHeader ().IsQosData ());
656 
657  return IsWithinSizeAndTimeLimits (mpdu->GetSize (), mpdu->GetHeader ().GetAddr1 (),
658  mpdu->GetHeader ().GetQosTid (), txVector,
659  ampduSize, ppduDurationLimit);
660 }
661 
662 bool
663 MacLow::IsWithinSizeAndTimeLimits (uint32_t mpduSize, Mac48Address receiver, uint8_t tid,
664  WifiTxVector txVector, uint32_t ampduSize, Time ppduDurationLimit)
665 {
666  NS_LOG_FUNCTION (this << mpduSize << receiver << +tid << txVector << ampduSize << ppduDurationLimit);
667 
668  if (ppduDurationLimit != Time::Min () && ppduDurationLimit.IsNegative ())
669  {
670  return false;
671  }
672 
673  WifiModulationClass modulation = txVector.GetMode ().GetModulationClass ();
674 
675  uint32_t maxAmpduSize = 0;
676  if (GetMpduAggregator ())
677  {
678  maxAmpduSize = GetMpduAggregator ()->GetMaxAmpduSize (receiver, tid, modulation);
679  }
680 
681  // If maxAmpduSize is null, then ampduSize must be null as well
682  NS_ASSERT (maxAmpduSize || ampduSize == 0);
683 
684  uint32_t ppduPayloadSize = mpduSize;
685 
686  // compute the correct size for A-MPDUs and S-MPDUs
687  if (ampduSize > 0 || modulation >= WIFI_MOD_CLASS_VHT)
688  {
689  ppduPayloadSize = GetMpduAggregator ()->GetSizeIfAggregated (mpduSize, ampduSize);
690  }
691 
692  if (maxAmpduSize > 0 && ppduPayloadSize > maxAmpduSize)
693  {
694  NS_LOG_DEBUG ("the frame does not meet the constraint on max A-MPDU size");
695  return false;
696  }
697 
698  // Get the maximum PPDU Duration based on the preamble type
699  Time maxPpduDuration = GetPpduMaxTime (txVector.GetPreambleType ());
700 
701  Time txTime = m_phy->CalculateTxDuration (ppduPayloadSize, txVector, m_phy->GetFrequency ());
702 
703  if ((ppduDurationLimit.IsStrictlyPositive () && txTime > ppduDurationLimit)
704  || (maxPpduDuration.IsStrictlyPositive () && txTime > maxPpduDuration))
705  {
706  NS_LOG_DEBUG ("the frame does not meet the constraint on max PPDU duration");
707  return false;
708  }
709 
710  return true;
711 }
712 
713 void
715 {
716  NS_LOG_FUNCTION (this);
717  NS_LOG_DEBUG ("PSDU reception started for " << psduDuration.ToDouble (Time::US)
718  << " us (txVector: " << txVector << ")");
719  NS_ASSERT (psduDuration.IsStrictlyPositive ());
720 
722  {
723  // we are waiting for a Normal Ack and something arrived
724  NS_LOG_DEBUG ("Rescheduling Normal Ack timeout");
728  &MacLow::NormalAckTimeout, this);
729  }
730  else if (m_blockAckTimeoutEvent.IsRunning ())
731  {
732  // we are waiting for a BlockAck and something arrived
733  NS_LOG_DEBUG ("Rescheduling Block Ack timeout");
737  &MacLow::BlockAckTimeout, this);
738  }
739  else if (m_ctsTimeoutEvent.IsRunning ())
740  {
741  // we are waiting for a CTS and something arrived
742  NS_LOG_DEBUG ("Rescheduling CTS timeout");
746  &MacLow::CtsTimeout, this);
747  }
749  {
750  NS_LOG_DEBUG ("Cannot reset NAV");
752  }
753 }
754 
755 void
757 {
758  NS_LOG_FUNCTION (this << *psdu);
759  NS_LOG_DEBUG ("rx failed");
760  if (IsCfPeriod () && m_currentPacket->GetHeader (0).IsCfPoll ())
761  {
762  NS_ASSERT (m_currentTxop != 0);
764  }
765  else if (m_cfAckInfo.expectCfAck)
766  {
767  NS_ASSERT (m_currentTxop != 0);
768  Ptr<Txop> txop = m_currentTxop;
769  m_currentTxop = 0;
770  txop->MissedAck ();
771  }
772  m_cfAckInfo.expectCfAck = false;
773  return;
774 }
775 
776 void
778 {
779  NS_LOG_DEBUG ("switching channel. Cancelling MAC pending events");
781  CancelAllEvents ();
783  {
785  }
788  m_currentPacket = 0;
789  m_currentTxop = 0;
790 }
791 
792 void
794 {
795  NS_LOG_DEBUG ("Device in sleep mode. Cancelling MAC pending events");
796  CancelAllEvents ();
798  {
800  }
803  m_currentPacket = 0;
804  m_currentTxop = 0;
805 }
806 
807 void
809 {
810  NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events");
811  CancelAllEvents ();
813  {
815  }
818  m_currentPacket = 0;
819  m_currentTxop = 0;
820 }
821 
822 void
823 MacLow::ReceiveOk (Ptr<WifiMacQueueItem> mpdu, double rxSnr, WifiTxVector txVector, bool ampduSubframe)
824 {
825  NS_LOG_FUNCTION (this << *mpdu << rxSnr << txVector);
826  /* An MPDU is received from the PHY.
827  * When we have handled this MPDU,
828  * we handle any packet present in the
829  * packet queue.
830  */
831  const WifiMacHeader& hdr = mpdu->GetHeader ();
832  Ptr<Packet> packet = mpdu->GetPacket ()->Copy ();
833 
834  bool isPrevNavZero = IsNavZero ();
835  NS_LOG_DEBUG ("duration/id=" << hdr.GetDuration ());
836  NotifyNav (packet, hdr);
837  if (hdr.IsRts ())
838  {
839  /* see section 9.2.5.7 802.11-1999
840  * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS
841  * period if the NAV at the STA receiving the RTS frame indicates that the medium is
842  * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle,
843  * that STA shall not respond to the RTS frame.
844  */
845  if (ampduSubframe)
846  {
847  NS_FATAL_ERROR ("Received RTS as part of an A-MPDU");
848  }
849  else
850  {
851  if (isPrevNavZero
852  && hdr.GetAddr1 () == m_self)
853  {
854  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
857  rxSnr, txVector.GetMode ());
860  hdr.GetAddr2 (),
861  hdr.GetDuration (),
862  txVector,
863  rxSnr);
864  }
865  else
866  {
867  NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
868  }
869  }
870  }
871  else if (hdr.IsCts ()
872  && hdr.GetAddr1 () == m_self
874  && m_currentPacket != 0)
875  {
876  if (ampduSubframe)
877  {
878  NS_FATAL_ERROR ("Received CTS as part of an A-MPDU");
879  }
880 
881  NS_LOG_DEBUG ("received cts from=" << m_currentPacket->GetAddr1 ());
882 
883  SnrTag tag;
884  packet->RemovePacketTag (tag);
886  rxSnr, txVector.GetMode ());
887  m_stationManager->ReportRtsOk (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0),
888  rxSnr, txVector.GetMode (), tag.Get ());
889 
895  hdr.GetDuration ());
896  }
897  else if (hdr.IsAck ()
898  && hdr.GetAddr1 () == m_self
901  {
902  NS_LOG_DEBUG ("receive ack from=" << m_currentPacket->GetAddr1 ());
903  SnrTag tag;
904  packet->RemovePacketTag (tag);
905  //When fragmentation is used, only update manager when the last fragment is acknowledged
906  if (!m_txParams.HasNextPacket ())
907  {
909  rxSnr, txVector.GetMode ());
910  m_stationManager->ReportDataOk (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0),
911  rxSnr, txVector.GetMode (), tag.Get (),
912  m_currentTxVector, m_currentPacket->GetSize ());
913  }
914  // cancel the Normal Ack timer
917  m_currentTxop->GotAck ();
918 
919  if (m_txParams.HasNextPacket ())
920  {
922  {
924  }
925  else
926  {
928  }
929  }
930  else if (m_currentPacket->GetHeader (0).IsQosData () && m_currentTxop->IsQosTxop () &&
932  {
934  {
936  }
937  else
938  {
940  }
941  }
942  else if (m_currentTxop->IsQosTxop ())
943  {
945  }
946  }
947  else if (hdr.IsBlockAck () && hdr.GetAddr1 () == m_self
950  {
951  NS_LOG_DEBUG ("got block ack from " << hdr.GetAddr2 ());
952  SnrTag tag;
953  packet->RemovePacketTag (tag);
954  CtrlBAckResponseHeader blockAck;
955  packet->RemoveHeader (blockAck);
958  m_currentTxop->GotBlockAck (&blockAck, hdr.GetAddr2 (), rxSnr, tag.Get (), m_currentTxVector);
959  // start next packet if TXOP remains, otherwise contend for accessing the channel again
962  {
964  {
966  }
967  else
968  {
970  }
971  }
972  else if (m_currentTxop->IsQosTxop ())
973  {
975  }
976  }
977  else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
978  {
979  CtrlBAckRequestHeader blockAckReq;
980  packet->RemoveHeader (blockAckReq);
981  if (!blockAckReq.IsMultiTid ())
982  {
983  uint8_t tid = blockAckReq.GetTidInfo ();
984  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), tid));
985  if (it != m_bAckAgreements.end ())
986  {
987  //Update block ack cache
988  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), tid));
989  NS_ASSERT (i != m_bAckCaches.end ());
990  (*i).second.UpdateWithBlockAckReq (blockAckReq.GetStartingSequence ());
991 
992  //NS_ASSERT (m_sendAckEvent.IsExpired ());
994  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
995  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
996  if ((*it).second.first.IsImmediateBlockAck ())
997  {
998  NS_LOG_DEBUG ("rx blockAckRequest/sendImmediateBlockAck from=" << hdr.GetAddr2 ());
1001  blockAckReq,
1002  hdr.GetAddr2 (),
1003  hdr.GetDuration (),
1004  txVector.GetMode (),
1005  rxSnr);
1006  }
1007  else
1008  {
1009  NS_FATAL_ERROR ("Delayed block ack not supported.");
1010  }
1011  }
1012  else
1013  {
1014  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
1015  }
1016  }
1017  else
1018  {
1019  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
1020  }
1021  }
1022  else if (hdr.IsCtl ())
1023  {
1024  if (hdr.IsCfEnd ())
1025  {
1026  NS_LOG_DEBUG ("rx CF-END ");
1027  m_cfpStart = NanoSeconds (0);
1029  {
1030  NS_ASSERT (m_currentTxop != 0);
1031  if (hdr.IsCfAck ())
1032  {
1033  m_currentTxop->GotAck ();
1034  }
1035  else
1036  {
1038  }
1039  }
1040  if (m_currentTxop != 0)
1041  {
1042  m_currentTxop->GotCfEnd ();
1043  }
1044  m_cfAckInfo.expectCfAck = false;
1045  }
1046  else
1047  {
1048  NS_LOG_DEBUG ("rx drop " << hdr.GetTypeString ());
1049  }
1050  }
1051  else if (hdr.GetAddr1 () == m_self)
1052  {
1053  if (hdr.IsCfPoll ())
1054  {
1056  if (m_cfAckInfo.expectCfAck && !hdr.IsCfAck ())
1057  {
1058  NS_ASSERT (m_currentTxop != 0);
1059  Ptr<Txop> txop = m_currentTxop;
1060  m_currentTxop = 0;
1061  txop->MissedAck ();
1062  m_cfAckInfo.expectCfAck = false;
1063  }
1064  }
1066  rxSnr, txVector.GetMode ());
1067  if (hdr.IsQosData () && ReceiveMpdu (mpdu))
1068  {
1069  /* From section 9.10.4 in IEEE 802.11:
1070  Upon the receipt of a QoS data frame from the originator for which
1071  the block ack agreement exists, the recipient shall buffer the MSDU
1072  regardless of the value of the Ack Policy subfield within the
1073  QoS Control field of the QoS data frame. */
1074  if (hdr.IsQosAck () && !ampduSubframe)
1075  {
1076  NS_LOG_DEBUG ("rx QoS unicast/sendAck from=" << hdr.GetAddr2 ());
1077  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1078 
1079  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (),
1080  hdr.GetAddr2 (), hdr.GetQosTid ());
1084  &MacLow::SendAckAfterData, this,
1085  hdr.GetAddr2 (),
1086  hdr.GetDuration (),
1087  txVector.GetMode (),
1088  rxSnr);
1089  }
1090  else if (hdr.IsQosBlockAck ())
1091  {
1092  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
1093  /* See section 11.5.3 in IEEE 802.11 for mean of this timer */
1094  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
1095  }
1096  return;
1097  }
1098  else if (hdr.IsQosData () && hdr.IsQosBlockAck ())
1099  {
1100  /* This happens if a packet with ack policy Block Ack is received and a block ack
1101  agreement for that packet doesn't exist.
1102 
1103  From section 11.5.3 in IEEE 802.11e:
1104  When a recipient does not have an active block ack for a TID, but receives
1105  data MPDUs with the Ack Policy subfield set to Block Ack, it shall discard
1106  them and shall send a DELBA frame using the normal access
1107  mechanisms. */
1108  AcIndex ac = QosUtilsMapTidToAc (hdr.GetQosTid ());
1109  m_edca[ac]->SendDelbaFrame (hdr.GetAddr2 (), hdr.GetQosTid (), false);
1110  return;
1111  }
1112  else if (hdr.IsQosData () && hdr.IsQosNoAck ())
1113  {
1114  if (ampduSubframe)
1115  {
1116  NS_LOG_DEBUG ("rx Ampdu with No Ack Policy from=" << hdr.GetAddr2 ());
1117  }
1118  else
1119  {
1120  NS_LOG_DEBUG ("rx unicast/noAck from=" << hdr.GetAddr2 ());
1121  }
1122  }
1123  else if (hdr.IsData () || hdr.IsMgt ())
1124  {
1125  if (hdr.IsProbeResp ())
1126  {
1127  // Apply SNR tag for probe response quality measurements
1128  SnrTag tag;
1129  tag.Set (rxSnr);
1130  packet->AddPacketTag (tag);
1131  mpdu = Create<WifiMacQueueItem> (packet, hdr);
1132  }
1133  if (hdr.IsMgt () && ampduSubframe)
1134  {
1135  NS_FATAL_ERROR ("Received management packet as part of an A-MPDU");
1136  }
1137  else
1138  {
1139  if (IsCfPeriod ())
1140  {
1141  if (hdr.HasData ())
1142  {
1143  m_cfAckInfo.appendCfAck = true;
1144  m_cfAckInfo.address = hdr.GetAddr2 ();
1145  }
1146  }
1147  else
1148  {
1149  NS_LOG_DEBUG ("rx unicast/sendAck from=" << hdr.GetAddr2 ());
1152  &MacLow::SendAckAfterData, this,
1153  hdr.GetAddr2 (),
1154  hdr.GetDuration (),
1155  txVector.GetMode (),
1156  rxSnr);
1157  }
1158  }
1159  }
1160  goto rxPacket;
1161  }
1162  else if (hdr.GetAddr1 ().IsGroup ())
1163  {
1164  if (ampduSubframe)
1165  {
1166  NS_FATAL_ERROR ("Received group addressed packet as part of an A-MPDU");
1167  }
1168  else
1169  {
1170  if (hdr.IsData () || hdr.IsMgt ())
1171  {
1172  NS_LOG_DEBUG ("rx group from=" << hdr.GetAddr2 ());
1173  if (hdr.IsBeacon ())
1174  {
1175  // Apply SNR tag for beacon quality measurements
1176  SnrTag tag;
1177  tag.Set (rxSnr);
1178  packet->AddPacketTag (tag);
1179  mpdu = Create<WifiMacQueueItem> (packet, hdr);
1180  }
1181  goto rxPacket;
1182  }
1183  }
1184  }
1185  else if (m_promisc)
1186  {
1187  NS_ASSERT (hdr.GetAddr1 () != m_self);
1188  if (hdr.IsData ())
1189  {
1190  goto rxPacket;
1191  }
1192  }
1193  else
1194  {
1195  if (m_cfAckInfo.expectCfAck && hdr.IsCfAck ())
1196  {
1197  m_cfAckInfo.expectCfAck = false;
1198  NS_ASSERT (m_currentTxop != 0);
1199  m_currentTxop->GotAck ();
1200  }
1201  NS_LOG_DEBUG ("rx not for me from=" << hdr.GetAddr2 ());
1202  }
1203  return;
1204 rxPacket:
1205  if (m_cfAckInfo.expectCfAck && hdr.IsCfAck ())
1206  {
1207  m_cfAckInfo.expectCfAck = false;
1208  NS_ASSERT (m_currentTxop != 0);
1209  m_currentTxop->GotAck ();
1210  }
1211  m_rxCallback (mpdu);
1212  return;
1213 }
1214 
1215 uint32_t
1217 {
1218  WifiMacHeader cfEnd;
1220  {
1221  cfEnd.SetType (WIFI_MAC_CTL_END_ACK);
1222  }
1223  else
1224  {
1225  cfEnd.SetType (WIFI_MAC_CTL_END);
1226  }
1227  return cfEnd.GetSize () + 4;
1228 }
1229 
1230 Time
1232 {
1233  WifiTxVector ackTxVector = GetAckTxVectorForData (to, dataTxVector.GetMode ());
1234  return GetAckDuration (ackTxVector);
1235 }
1236 
1237 Time
1239 {
1240  NS_ASSERT (ackTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //Ack should always use non-HT PPDU (HT PPDU cases not supported yet)
1241  return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, m_phy->GetFrequency ());
1242 }
1243 
1244 Time
1245 MacLow::GetBlockAckDuration (WifiTxVector blockAckReqTxVector, BlockAckType type) const
1246 {
1247  /*
1248  * For immediate Basic BlockAck we should transmit the frame with the same WifiMode
1249  * as the BlockAckReq.
1250  */
1251  return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, m_phy->GetFrequency ());
1252 }
1253 
1254 Time
1256 {
1257  return m_phy->CalculateTxDuration (GetBlockAckRequestSize (type), blockAckReqTxVector, m_phy->GetFrequency ());
1258 }
1259 
1260 Time
1262 {
1263  WifiTxVector ctsTxVector = GetCtsTxVectorForRts (to, rtsTxVector.GetMode ());
1264  return GetCtsDuration (ctsTxVector);
1265 }
1266 
1267 Time
1269 {
1270  NS_ASSERT (ctsTxVector.GetMode ().GetModulationClass () != WIFI_MOD_CLASS_HT); //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
1271  return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetFrequency ());
1272 }
1273 
1276 {
1277  return m_stationManager->GetRtsTxVector (item->GetHeader ().GetAddr1 ());
1278 }
1279 
1282 {
1283  return m_stationManager->GetDataTxVector (item->GetHeader ());
1284 }
1285 
1286 Time
1288  Mac48Address receiver) const
1289 {
1290  NS_LOG_FUNCTION (this << receiver << dataTxVector << params);
1291 
1292  Time duration = Seconds (0);
1293  if (params.MustWaitNormalAck ())
1294  {
1295  duration += GetSifs ();
1296  duration += GetAckDuration (receiver, dataTxVector);
1297  }
1298  else if (params.MustWaitBlockAck ())
1299  {
1300  duration += GetSifs ();
1301  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_self, dataTxVector.GetMode ());
1302  duration += GetBlockAckDuration (blockAckReqTxVector, params.GetBlockAckType ());
1303  }
1304  else if (params.MustSendBlockAckRequest ())
1305  {
1306  duration += 2 * GetSifs ();
1307  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (m_self, dataTxVector.GetMode ());
1308  duration += GetBlockAckRequestDuration (blockAckReqTxVector, params.GetBlockAckRequestType ());
1309  duration += GetBlockAckDuration (blockAckReqTxVector, params.GetBlockAckRequestType ());
1310  }
1311  return duration;
1312 }
1313 
1314 WifiMode
1316 {
1331  NS_LOG_FUNCTION (this << reqMode);
1333  bool found = false;
1334  //First, search the BSS Basic Rate set
1335  for (uint8_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
1336  {
1337  WifiMode testMode = m_stationManager->GetBasicMode (i);
1338  if ((!found || testMode.IsHigherDataRate (mode))
1339  && (!testMode.IsHigherDataRate (reqMode))
1341  {
1342  mode = testMode;
1343  //We've found a potentially-suitable transmit rate, but we
1344  //need to continue and consider all the basic rates before
1345  //we can be sure we've got the right one.
1346  found = true;
1347  }
1348  }
1350  {
1351  if (!found)
1352  {
1353  mode = m_stationManager->GetDefaultMcs ();
1354  for (uint8_t i = 0; i != m_stationManager->GetNBasicMcs (); i++)
1355  {
1356  WifiMode testMode = m_stationManager->GetBasicMcs (i);
1357  if ((!found || testMode.IsHigherDataRate (mode))
1358  && (!testMode.IsHigherDataRate (reqMode))
1359  && (testMode.GetModulationClass () == reqMode.GetModulationClass ()))
1360  {
1361  mode = testMode;
1362  //We've found a potentially-suitable transmit rate, but we
1363  //need to continue and consider all the basic rates before
1364  //we can be sure we've got the right one.
1365  found = true;
1366  }
1367  }
1368  }
1369  }
1370  //If we found a suitable rate in the BSSBasicRateSet, then we are
1371  //done and can return that mode.
1372  if (found)
1373  {
1374  NS_LOG_DEBUG ("MacLow::GetControlAnswerMode returning " << mode);
1375  return mode;
1376  }
1377 
1395  for (uint8_t idx = 0; idx < m_phy->GetNModes (); idx++)
1396  {
1397  WifiMode thismode = m_phy->GetMode (idx);
1398  /* If the rate:
1399  *
1400  * - is a mandatory rate for the PHY, and
1401  * - is equal to or faster than our current best choice, and
1402  * - is less than or equal to the rate of the received frame, and
1403  * - is of the same modulation class as the received frame
1404  *
1405  * ...then it's our best choice so far.
1406  */
1407  if (thismode.IsMandatory ()
1408  && (!found || thismode.IsHigherDataRate (mode))
1409  && (!thismode.IsHigherDataRate (reqMode))
1411  {
1412  mode = thismode;
1413  //As above; we've found a potentially-suitable transmit
1414  //rate, but we need to continue and consider all the
1415  //mandatory rates before we can be sure we've got the right one.
1416  found = true;
1417  }
1418  }
1420  {
1421  for (uint8_t idx = 0; idx < m_phy->GetNMcs (); idx++)
1422  {
1423  WifiMode thismode = m_phy->GetMcs (idx);
1424  if (thismode.IsMandatory ()
1425  && (!found || thismode.IsHigherDataRate (mode))
1426  && (!thismode.IsHigherCodeRate (reqMode))
1427  && (thismode.GetModulationClass () == reqMode.GetModulationClass ()))
1428  {
1429  mode = thismode;
1430  //As above; we've found a potentially-suitable transmit
1431  //rate, but we need to continue and consider all the
1432  //mandatory rates before we can be sure we've got the right one.
1433  found = true;
1434  }
1435  }
1436  }
1437 
1447  if (!found)
1448  {
1449  NS_FATAL_ERROR ("Can't find response rate for " << reqMode);
1450  }
1451 
1452  NS_LOG_DEBUG ("MacLow::GetControlAnswerMode returning " << mode);
1453  return mode;
1454 }
1455 
1458 {
1459  NS_ASSERT (!to.IsGroup ());
1460  WifiMode ctsMode = GetControlAnswerMode (rtsTxMode);
1461  WifiTxVector v;
1462  v.SetMode (ctsMode);
1466  uint16_t ctsTxGuardInterval = ConvertGuardIntervalToNanoSeconds (ctsMode, m_phy->GetShortGuardInterval (), m_phy->GetGuardInterval ());
1467  v.SetGuardInterval (ctsTxGuardInterval);
1468  v.SetNss (1);
1469  return v;
1470 }
1471 
1474 {
1475  NS_ASSERT (!to.IsGroup ());
1476  WifiMode ackMode = GetControlAnswerMode (dataTxMode);
1477  WifiTxVector v;
1478  v.SetMode (ackMode);
1482  uint16_t ackTxGuardInterval = ConvertGuardIntervalToNanoSeconds (ackMode, m_phy->GetShortGuardInterval (), m_phy->GetGuardInterval ());
1483  v.SetGuardInterval (ackTxGuardInterval);
1484  v.SetNss (1);
1485  return v;
1486 }
1487 
1490 {
1491  NS_ASSERT (!to.IsGroup ());
1492  WifiMode blockAckMode = GetControlAnswerMode (dataTxMode);
1493  WifiTxVector v;
1494  v.SetMode (blockAckMode);
1498 uint16_t blockAckTxGuardInterval = ConvertGuardIntervalToNanoSeconds (blockAckMode, m_phy->GetShortGuardInterval (), m_phy->GetGuardInterval ());
1499  v.SetGuardInterval (blockAckTxGuardInterval);
1500  v.SetNss (1);
1501  return v;
1502 }
1503 
1506 {
1507  return GetCtsTxVector (to, rtsTxMode);
1508 }
1509 
1512 {
1513  return GetAckTxVector (to, dataTxMode);
1514 }
1515 
1516 Time
1518  const WifiMacHeader* hdr,
1519  const MacLowTransmissionParameters& params,
1520  uint32_t fragmentSize) const
1521 {
1522  Ptr<const WifiMacQueueItem> item = Create<const WifiMacQueueItem> (packet, *hdr);
1523  Time txTime = CalculateOverheadTxTime (item, params);
1524  uint32_t dataSize;
1525  if (fragmentSize > 0)
1526  {
1527  Ptr<const Packet> fragment = Create<Packet> (fragmentSize);
1528  dataSize = GetSize (fragment, hdr, m_currentPacket && m_currentPacket->IsAggregate ());
1529  }
1530  else
1531  {
1532  dataSize = GetSize (packet, hdr, m_currentPacket && m_currentPacket->IsAggregate ());
1533  }
1534  txTime += m_phy->CalculateTxDuration (dataSize, GetDataTxVector (item), m_phy->GetFrequency ());
1535  return txTime;
1536 }
1537 
1538 Time
1540  const MacLowTransmissionParameters& params) const
1541 {
1542  Time txTime = Seconds (0);
1543  if (params.MustSendRts ())
1544  {
1545  WifiTxVector rtsTxVector = GetRtsTxVector (item);
1546  txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetFrequency ());
1547  txTime += GetCtsDuration (item->GetHeader ().GetAddr1 (), rtsTxVector);
1548  txTime += Time (GetSifs () * 2);
1549  }
1550  txTime += GetResponseDuration (params, GetDataTxVector (item), item->GetHeader ().GetAddr1 ());
1551 
1552  return txTime;
1553 }
1554 
1555 Time
1557  const WifiMacHeader* hdr,
1558  const MacLowTransmissionParameters& params) const
1559 {
1560  Time txTime = CalculateOverallTxTime (packet, hdr, params);
1561  if (params.HasNextPacket ())
1562  {
1563  WifiTxVector dataTxVector = GetDataTxVector (Create<const WifiMacQueueItem> (packet, *hdr));
1564  txTime += GetSifs ();
1565  txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, m_phy->GetFrequency ());
1566  }
1567  return txTime;
1568 }
1569 
1570 void
1572 {
1574  if (hdr.GetRawDuration () > 32767)
1575  {
1576  //All stations process Duration field values less than or equal to 32 767 from valid data frames
1577  //to update their NAV settings as appropriate under the coordination function rules.
1578  return;
1579  }
1580  if (hdr.IsCfEnd () && hdr.GetAddr2 () == m_bssid)
1581  {
1582  //see section 9.3.2.2 802.11-1999
1583  DoNavResetNow (Seconds (0));
1584  return;
1585  }
1586  else if (hdr.GetAddr1 () != m_self)
1587  {
1588  // see section 9.2.5.4 802.11-1999
1589  Time duration = hdr.GetDuration ();
1590  bool navUpdated = DoNavStartNow (duration);
1591  if (hdr.IsRts () && navUpdated)
1592  {
1601  WifiMacHeader cts;
1602  cts.SetType (WIFI_MAC_CTL_CTS);
1603  WifiTxVector txVector = GetRtsTxVector (Create<const WifiMacQueueItem> (packet, hdr));
1604  Time navCounterResetCtsMissedDelay =
1605  m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, m_phy->GetFrequency ()) +
1606  Time (2 * GetSifs ()) + Time (2 * GetSlotTime ()) +
1608  m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
1609  &MacLow::DoNavResetNow, this,
1610  Seconds (0));
1611  }
1612  }
1613 }
1614 
1615 void
1617 {
1618  NS_LOG_FUNCTION (this << duration);
1619  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1620  {
1621  (*i)->NotifyNavResetNow (duration);
1622  }
1624  m_lastNavDuration = duration;
1625 }
1626 
1627 bool
1629 {
1630  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1631  {
1632  (*i)->NotifyNavStartNow (duration);
1633  }
1634  Time newNavEnd = Simulator::Now () + duration;
1635  Time oldNavEnd = m_lastNavStart + m_lastNavDuration;
1636  if (newNavEnd > oldNavEnd)
1637  {
1639  m_lastNavDuration = duration;
1640  return true;
1641  }
1642  return false;
1643 }
1644 
1645 void
1647 {
1648  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1649  {
1650  (*i)->NotifyAckTimeoutStartNow (duration);
1651  }
1652 }
1653 
1654 void
1656 {
1657  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1658  {
1659  (*i)->NotifyAckTimeoutResetNow ();
1660  }
1661 }
1662 
1663 void
1665 {
1666  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1667  {
1668  (*i)->NotifyCtsTimeoutStartNow (duration);
1669  }
1670 }
1671 
1672 void
1674 {
1675  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1676  {
1677  (*i)->NotifyCtsTimeoutResetNow ();
1678  }
1679 }
1680 
1681 void
1683 {
1684  NS_LOG_FUNCTION (this << psdu << txVector);
1685 
1686  NS_ASSERT (psdu->GetNMpdus ());
1687  const WifiMacHeader& hdr = (*psdu->begin ())->GetHeader ();
1688 
1689  NS_LOG_DEBUG ("send " << hdr.GetTypeString () <<
1690  ", to=" << hdr.GetAddr1 () <<
1691  ", size=" << psdu->GetSize () <<
1692  ", mode=" << txVector.GetMode () <<
1693  ", preamble=" << txVector.GetPreambleType () <<
1694  ", duration=" << hdr.GetDuration () <<
1695  ", seq=0x" << std::hex << hdr.GetSequenceControl () << std::dec);
1696 
1697  if (hdr.IsCfPoll () && m_stationManager->GetPcfSupported ())
1698  {
1699  Simulator::Schedule (GetPifs () + m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetFrequency ()), &MacLow::CfPollTimeout, this);
1700  }
1701  if (hdr.IsBeacon () && m_stationManager->GetPcfSupported ())
1702  {
1704  {
1706  }
1708  }
1709  else if (hdr.IsCfEnd () && m_stationManager->GetPcfSupported ())
1710  {
1711  m_cfpStart = NanoSeconds (0);
1713  m_cfAckInfo.appendCfAck = false;
1714  m_cfAckInfo.expectCfAck = false;
1715  }
1716  else if (IsCfPeriod () && hdr.HasData ())
1717  {
1718  m_cfAckInfo.expectCfAck = true;
1719  }
1720 
1721  if (psdu->IsSingle ())
1722  {
1723  txVector.SetAggregation (true);
1724  NS_LOG_DEBUG ("Sending S-MPDU");
1725  }
1726  else if (psdu->IsAggregate ())
1727  {
1728  txVector.SetAggregation (true);
1729  NS_LOG_DEBUG ("Sending A-MPDU");
1730  }
1731  else
1732  {
1733  NS_LOG_DEBUG ("Sending non aggregate MPDU");
1734  }
1735 
1736  for (auto& mpdu : *PeekPointer (psdu))
1737  {
1738  if (mpdu->GetHeader ().IsQosData ())
1739  {
1740  auto edcaIt = m_edca.find (QosUtilsMapTidToAc (mpdu->GetHeader ().GetQosTid ()));
1741  edcaIt->second->CompleteMpduTx (mpdu);
1742  }
1743  }
1744  m_phy->Send (psdu, txVector);
1745 }
1746 
1747 void
1749 {
1750  NS_LOG_FUNCTION (this);
1751  //to be reworked
1752  bool busy = false;
1753  for (ChannelAccessManagersCI i = m_channelAccessManagers.begin (); i != m_channelAccessManagers.end (); i++)
1754  {
1755  busy = (*i)->IsBusy ();
1756  }
1757  if (!busy)
1758  {
1759  NS_ASSERT (m_currentTxop != 0);
1761  m_cfAckInfo.expectCfAck = false;
1762  }
1763 }
1764 
1765 void
1767 {
1768  NS_LOG_FUNCTION (this);
1769  NS_LOG_DEBUG ("cts timeout");
1773  m_stationManager->ReportRtsFailed (m_currentPacket->GetAddr1 (), &m_currentPacket->GetHeader (0));
1774 
1775  Ptr<QosTxop> qosTxop = DynamicCast<QosTxop> (m_currentTxop);
1776  if (qosTxop != 0)
1777  {
1779  }
1780  else
1781  {
1783  }
1784  m_currentTxop = 0;
1785 }
1786 
1787 void
1789 {
1790  NS_LOG_FUNCTION (this);
1791  NS_LOG_DEBUG ("normal ack timeout");
1795  Ptr<Txop> txop = m_currentTxop;
1796  m_currentTxop = 0;
1797  txop->MissedAck ();
1798 }
1799 
1800 void
1802 {
1803  NS_LOG_FUNCTION (this);
1804  NS_LOG_DEBUG ("block ack timeout");
1805  Ptr<Txop> txop = m_currentTxop;
1806  m_currentTxop = 0;
1807  txop->MissedBlockAck (m_currentPacket->GetNMpdus ());
1808 }
1809 
1810 void
1812 {
1813  NS_LOG_FUNCTION (this);
1814  /* send an RTS for this packet. */
1815  WifiMacHeader rts;
1816  rts.SetType (WIFI_MAC_CTL_RTS);
1817  rts.SetDsNotFrom ();
1818  rts.SetDsNotTo ();
1819  rts.SetNoRetry ();
1820  rts.SetNoMoreFragments ();
1821  rts.SetAddr1 (m_currentPacket->GetAddr1 ());
1822  rts.SetAddr2 (m_self);
1823  WifiTxVector rtsTxVector = GetRtsTxVector (*m_currentPacket->begin ());
1824  Time duration = Seconds (0);
1825 
1826  duration += GetSifs ();
1827  duration += GetCtsDuration (m_currentPacket->GetAddr1 (), rtsTxVector);
1828  duration += GetSifs ();
1829  duration += m_phy->CalculateTxDuration (m_currentPacket->GetSize (),
1831  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1832  if (m_txParams.HasNextPacket ())
1833  {
1836  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1837  }
1838  rts.SetDuration (duration);
1839 
1840  Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, m_phy->GetFrequency ());
1841  // After transmitting an RTS frame, the STA shall wait for a CTSTimeout interval with
1842  // a value of aSIFSTime + aSlotTime + aRxPHYStartDelay (IEEE 802.11-2016 sec. 10.3.2.7).
1843  // aRxPHYStartDelay equals the time to transmit the PHY header.
1844  Time timerDelay = txDuration + GetSifs () + GetSlotTime ()
1847  NotifyCtsTimeoutStartNow (timerDelay);
1849 
1850  ForwardDown (Create<const WifiPsdu> (Create<Packet> (), rts), rtsTxVector);
1851 }
1852 
1853 void
1855 {
1856  Time txDuration = m_phy->CalculateTxDuration (m_currentPacket->GetSize (), dataTxVector, m_phy->GetFrequency ());
1857  if (m_txParams.MustWaitNormalAck () && !IsCfPeriod ())
1858  {
1859  // the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
1860  // at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
1861  // aRxPHYStartDelay equals the time to transmit the PHY header.
1862  WifiTxVector ackTxVector = GetAckTxVector (m_currentPacket->GetAddr1 (),
1863  dataTxVector.GetMode ());
1864  Time timerDelay = txDuration + GetSifs () + GetSlotTime ()
1867  NotifyAckTimeoutStartNow (timerDelay);
1869  }
1870  else if (m_txParams.MustWaitBlockAck ())
1871  {
1872  // the timeout duration is "aSIFSTime + aSlotTime + aRxPHYStartDelay, starting
1873  // at the PHY-TXEND.confirm primitive" (section 10.3.2.9 or 10.22.2.2 of 802.11-2016).
1874  // aRxPHYStartDelay equals the time to transmit the PHY header.
1875  WifiTxVector blockAckTxVector = GetBlockAckTxVector (m_currentPacket->GetAddr1 (),
1876  dataTxVector.GetMode ());
1877  Time timerDelay = txDuration + GetSifs () + GetSlotTime ()
1878  + m_phy->CalculatePhyPreambleAndHeaderDuration (blockAckTxVector);
1880  NotifyAckTimeoutStartNow (timerDelay);
1882  }
1883  else if (m_txParams.HasNextPacket ())
1884  {
1886  Time delay = txDuration;
1888  {
1889  delay += GetRifs ();
1890  }
1891  else
1892  {
1893  delay += GetSifs ();
1894  }
1896  }
1897  else if (m_currentPacket->GetHeader (0).IsQosData () && m_currentTxop->IsQosTxop () &&
1899  {
1900  Time delay = txDuration;
1902  {
1903  delay += GetRifs ();
1904  }
1905  else
1906  {
1907  delay += GetSifs ();
1908  }
1910  }
1911  else
1912  {
1913  // since we do not expect any timer to be triggered.
1915  }
1916 }
1917 
1918 void
1920 {
1921  NS_LOG_FUNCTION (this);
1922  /* send this packet directly. No RTS is needed. */
1924 
1925  if (!IsCfPeriod ())
1926  {
1928  if (m_txParams.HasNextPacket ())
1929  {
1931  {
1932  duration += GetRifs ();
1933  }
1934  else
1935  {
1936  duration += GetSifs ();
1937  }
1940  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
1941  }
1942  m_currentPacket->SetDuration (duration);
1943  }
1944  else
1945  {
1946  if (m_currentPacket->GetHeader (0).IsCfEnd ())
1947  {
1948  m_currentPacket->GetHeader (0).SetRawDuration (0);
1949  }
1950  else
1951  {
1952  m_currentPacket->GetHeader (0).SetRawDuration (32768);
1953  }
1954  }
1955 
1956  if (!m_currentPacket->IsAggregate ())
1957  {
1959  {
1960  switch (m_currentPacket->GetHeader (0).GetType ())
1961  {
1962  case WIFI_MAC_DATA:
1963  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_CFACK, false);
1964  break;
1965  case WIFI_MAC_DATA_CFPOLL:
1966  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_CFACK_CFPOLL, false);
1967  break;
1968  case WIFI_MAC_DATA_NULL:
1969  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_NULL_CFACK, false);
1970  break;
1972  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_DATA_NULL_CFACK_CFPOLL, false);
1973  break;
1974  case WIFI_MAC_CTL_END:
1975  m_currentPacket->GetHeader (0).SetType (WIFI_MAC_CTL_END_ACK, false);
1976  break;
1977  default:
1978  NS_ASSERT (false);
1979  break;
1980  }
1982  //Standard says that, for frames of type Data+CF-Ack, Data+CF-Poll+CF-Ack, and CF-Poll+CF-Ack,
1983  //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.
1984  //This ideally requires the rate manager to handle this case, but this requires to update all rate manager classes.
1985  //Instead, we simply fetch two TxVector and we select the one with the lowest data rate.
1986  //This should be later changed, at the latest once HCCA is implemented for HT/VHT/HE stations.
1987  WifiMacHeader tmpHdr = m_currentPacket->GetHeader (0);
1988  tmpHdr.SetAddr1 (m_cfAckInfo.address);
1989  WifiTxVector tmpTxVector = GetDataTxVector (Create<const WifiMacQueueItem> (m_currentPacket->GetPayload (0), tmpHdr));
1990  if (tmpTxVector.GetMode ().GetDataRate (tmpTxVector) < m_currentTxVector.GetMode ().GetDataRate (m_currentTxVector))
1991  {
1992  m_currentTxVector = tmpTxVector;
1993  }
1994  m_cfAckInfo.appendCfAck = false;
1996  }
1997  }
1999  {
2000  Ptr<QosTxop> qosTxop = DynamicCast<QosTxop> (m_currentTxop);
2001  NS_ASSERT (qosTxop != 0);
2002  auto bar = qosTxop->PrepareBlockAckRequest (m_currentPacket->GetAddr1 (), *m_currentPacket->GetTids ().begin ());
2003  qosTxop->ScheduleBar (bar);
2004  }
2006 }
2007 
2008 bool
2009 MacLow::IsNavZero (void) const
2010 {
2012 }
2013 
2014 void
2016 {
2017  WifiMacHeader cts;
2018  cts.SetType (WIFI_MAC_CTL_CTS);
2019  cts.SetDsNotFrom ();
2020  cts.SetDsNotTo ();
2021  cts.SetNoMoreFragments ();
2022  cts.SetNoRetry ();
2023  cts.SetAddr1 (m_self);
2024 
2025  WifiTxVector ctsTxVector = GetRtsTxVector (*m_currentPacket->begin ());
2026  Time duration = Seconds (0);
2027 
2028  duration += GetSifs ();
2029  duration += m_phy->CalculateTxDuration (m_currentPacket->GetSize (),
2031  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
2032  if (m_txParams.HasNextPacket ())
2033  {
2034  duration += GetSifs ();
2037  duration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
2038  }
2039 
2040  cts.SetDuration (duration);
2041 
2042  ForwardDown (Create<const WifiPsdu> (Create<Packet> (), cts), ctsTxVector);
2043 
2044  Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, m_phy->GetFrequency ());
2045  txDuration += GetSifs ();
2047 
2048  m_sendDataEvent = Simulator::Schedule (txDuration,
2049  &MacLow::SendDataAfterCts, this,
2050  duration);
2051 }
2052 
2053 void
2054 MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
2055 {
2056  NS_LOG_FUNCTION (this << source << duration << rtsTxVector.GetMode () << rtsSnr);
2057  /* send a CTS when you receive a RTS
2058  * right after SIFS.
2059  */
2060  WifiTxVector ctsTxVector = GetCtsTxVector (source, rtsTxVector.GetMode ());
2061  WifiMacHeader cts;
2062  cts.SetType (WIFI_MAC_CTL_CTS);
2063  cts.SetDsNotFrom ();
2064  cts.SetDsNotTo ();
2065  cts.SetNoMoreFragments ();
2066  cts.SetNoRetry ();
2067  cts.SetAddr1 (source);
2068  duration -= GetCtsDuration (source, rtsTxVector);
2069  duration -= GetSifs ();
2070  NS_ASSERT (duration.IsPositive ());
2071  cts.SetDuration (duration);
2072 
2073  Ptr<Packet> packet = Create<Packet> ();
2074 
2075  SnrTag tag;
2076  tag.Set (rtsSnr);
2077  packet->AddPacketTag (tag);
2078 
2079  //CTS should always use non-HT PPDU (HT PPDU cases not supported yet)
2080  ForwardDown (Create<const WifiPsdu> (packet, cts), ctsTxVector);
2081 }
2082 
2083 void
2085 {
2086  NS_LOG_FUNCTION (this);
2087  /* send the third step in a
2088  * RTS/CTS/Data/Ack handshake
2089  */
2090  NS_ASSERT (m_currentPacket != 0);
2091 
2093  Time newDuration = GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
2094  if (m_txParams.HasNextPacket ())
2095  {
2097  {
2098  newDuration += GetRifs ();
2099  }
2100  else
2101  {
2102  newDuration += GetSifs ();
2103  }
2105  newDuration += GetResponseDuration (m_txParams, m_currentTxVector, m_currentPacket->GetAddr1 ());
2106  }
2107 
2109  duration -= txDuration;
2110  duration -= GetSifs ();
2111 
2112  duration = std::max (duration, newDuration);
2113  NS_ASSERT (duration.IsPositive ());
2114  m_currentPacket->SetDuration (duration);
2116  {
2117  Ptr<QosTxop> qosTxop = DynamicCast<QosTxop> (m_currentTxop);
2118  NS_ASSERT (qosTxop != 0);
2119  auto bar = qosTxop->PrepareBlockAckRequest (m_currentPacket->GetAddr1 (), *m_currentPacket->GetTids ().begin ());
2120  qosTxop->ScheduleBar (bar);
2121  }
2123 }
2124 
2125 void
2127 {
2128  NS_LOG_FUNCTION (this);
2130 }
2131 
2132 void
2134 {
2135  NS_LOG_FUNCTION (this);
2137 }
2138 
2139 void
2141 {
2142  NS_LOG_FUNCTION (this);
2143  if (m_currentPacket->GetHeader (0).IsBeacon () && m_stationManager->GetPcfSupported ())
2144  {
2146  }
2147  if (!m_cfAckInfo.expectCfAck)
2148  {
2149  Ptr<Txop> txop = m_currentTxop;
2150  txop->EndTxNoAck ();
2151  }
2152  if (!IsCfPeriod ())
2153  {
2154  m_currentTxop = 0;
2155  }
2156 }
2157 
2158 void
2159 MacLow::SendAckAfterData (Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
2160 {
2161  NS_LOG_FUNCTION (this);
2162  // send an Ack, after SIFS, when you receive a packet
2163  WifiTxVector ackTxVector = GetAckTxVector (source, dataTxMode);
2164  WifiMacHeader ack;
2165  ack.SetType (WIFI_MAC_CTL_ACK);
2166  ack.SetDsNotFrom ();
2167  ack.SetDsNotTo ();
2168  ack.SetNoRetry ();
2169  ack.SetNoMoreFragments ();
2170  ack.SetAddr1 (source);
2171  // 802.11-2012, Section 8.3.1.4: Duration/ID is received duration value
2172  // minus the time to transmit the Ack frame and its SIFS interval
2173  duration -= GetAckDuration (ackTxVector);
2174  duration -= GetSifs ();
2175  NS_ASSERT_MSG (duration.IsPositive (), "Please provide test case to maintainers if this assert is hit.");
2176  ack.SetDuration (duration);
2177 
2178  Ptr<Packet> packet = Create<Packet> ();
2179 
2180  SnrTag tag;
2181  tag.Set (dataSnr);
2182  packet->AddPacketTag (tag);
2183 
2184  //Ack should always use non-HT PPDU (HT PPDU cases not supported yet)
2185  ForwardDown (Create<const WifiPsdu> (packet, ack), ackTxVector);
2186 }
2187 
2188 bool
2190 {
2191  const WifiMacHeader& hdr = mpdu->GetHeader ();
2192 
2196  {
2197  Mac48Address originator = hdr.GetAddr2 ();
2198  uint8_t tid = 0;
2199  if (hdr.IsQosData ())
2200  {
2201  tid = hdr.GetQosTid ();
2202  }
2203  uint16_t seqNumber = hdr.GetSequenceNumber ();
2204  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2205  if (it != m_bAckAgreements.end ())
2206  {
2207  //Implement HT immediate BlockAck support for HT Delayed BlockAck is not added yet
2208  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), seqNumber))
2209  {
2210  StoreMpduIfNeeded (mpdu);
2211  if (!IsInWindow (hdr.GetSequenceNumber (), (*it).second.first.GetStartingSequence (), (*it).second.first.GetBufferSize ()))
2212  {
2213  uint16_t delta = (seqNumber - (*it).second.first.GetWinEnd () + 4096) % 4096;
2214  NS_ASSERT (delta > 0);
2215  uint16_t bufferSize = (*it).second.first.GetBufferSize ();
2216  uint16_t startingSeq = (seqNumber - bufferSize + 1 + 4096) % 4096;
2217  (*it).second.first.SetStartingSequence (startingSeq);
2218  RxCompleteBufferedPacketsWithSmallerSequence ((*it).second.first.GetStartingSequenceControl (), originator, tid);
2219  }
2220  RxCompleteBufferedPacketsUntilFirstLost (originator, tid); //forwards up packets starting from winstart and set winstart to last +1
2221  }
2222  return true;
2223  }
2224  return false;
2225  }
2226  return StoreMpduIfNeeded (mpdu);
2227 }
2228 
2229 bool
2231 {
2232  const WifiMacHeader& hdr = mpdu->GetHeader ();
2233 
2234  AgreementsI it = m_bAckAgreements.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2235  if (it != m_bAckAgreements.end ())
2236  {
2237  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2238  uint32_t mappedSeqControl = QosUtilsMapSeqControlToUniqueInteger (hdr.GetSequenceControl (), endSequence);
2239 
2240  BufferedPacketI i = (*it).second.second.begin ();
2241  for (; i != (*it).second.second.end ()
2242  && QosUtilsMapSeqControlToUniqueInteger ((*i)->GetHeader ().GetSequenceControl (), endSequence) < mappedSeqControl; i++)
2243  {
2244  }
2245  (*it).second.second.insert (i, mpdu);
2246 
2247  //Update block ack cache
2248  BlockAckCachesI j = m_bAckCaches.find (std::make_pair (hdr.GetAddr2 (), hdr.GetQosTid ()));
2249  NS_ASSERT (j != m_bAckCaches.end ());
2250  (*j).second.UpdateWithMpdu (&hdr);
2251  return true;
2252  }
2253  return false;
2254 }
2255 
2256 void
2258  uint16_t startingSeq)
2259 {
2260  NS_LOG_FUNCTION (this);
2261  uint8_t tid = respHdr->GetTid ();
2262  BlockAckAgreement agreement (originator, tid);
2263  if (respHdr->IsImmediateBlockAck ())
2264  {
2265  agreement.SetImmediateBlockAck ();
2266  }
2267  else
2268  {
2269  agreement.SetDelayedBlockAck ();
2270  }
2271  agreement.SetAmsduSupport (respHdr->IsAmsduSupported ());
2272  agreement.SetBufferSize (respHdr->GetBufferSize () + 1);
2273  agreement.SetTimeout (respHdr->GetTimeout ());
2274  agreement.SetStartingSequence (startingSeq);
2275 
2276  std::list<Ptr<WifiMacQueueItem>> buffer (0);
2277  AgreementKey key (originator, respHdr->GetTid ());
2278  AgreementValue value (agreement, buffer);
2279  m_bAckAgreements.insert (std::make_pair (key, value));
2280 
2281  BlockAckCache cache;
2282  cache.Init (startingSeq, respHdr->GetBufferSize () + 1);
2283  m_bAckCaches.insert (std::make_pair (key, cache));
2284 
2285  if (respHdr->GetTimeout () != 0)
2286  {
2287  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, respHdr->GetTid ()));
2288  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2289 
2290  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2291 
2292  it->second.first.m_inactivityEvent = Simulator::Schedule (timeout,
2294  m_edca[ac], originator, tid, false);
2295  }
2296 }
2297 
2298 void
2300 {
2301  NS_LOG_FUNCTION (this);
2302  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2303  if (it != m_bAckAgreements.end ())
2304  {
2305  RxCompleteBufferedPacketsWithSmallerSequence (it->second.first.GetStartingSequenceControl (), originator, tid);
2306  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2307  m_bAckAgreements.erase (it);
2308  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2309  NS_ASSERT (i != m_bAckCaches.end ());
2310  m_bAckCaches.erase (i);
2311  }
2312 }
2313 
2314 void
2316 {
2317  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2318  if (it != m_bAckAgreements.end ())
2319  {
2320  uint16_t endSequence = ((*it).second.first.GetStartingSequence () + 2047) % 4096;
2321  uint32_t mappedStart = QosUtilsMapSeqControlToUniqueInteger (seq, endSequence);
2322  BufferedPacketI last = (*it).second.second.begin ();
2323  uint16_t guard = 0;
2324  if (last != (*it).second.second.end ())
2325  {
2326  guard = (*(*it).second.second.begin ())->GetHeader ().GetSequenceControl ();
2327  }
2328  BufferedPacketI i = (*it).second.second.begin ();
2329  for (; i != (*it).second.second.end ()
2330  && QosUtilsMapSeqControlToUniqueInteger ((*i)->GetHeader ().GetSequenceControl (), endSequence) < mappedStart; )
2331  {
2332  if (guard == (*i)->GetHeader ().GetSequenceControl ())
2333  {
2334  if (!(*i)->GetHeader ().IsMoreFragments ())
2335  {
2336  while (last != i)
2337  {
2338  m_rxCallback (*last);
2339  last++;
2340  }
2341  m_rxCallback (*last);
2342  last++;
2343  /* go to next packet */
2344  while (i != (*it).second.second.end () && guard == (*i)->GetHeader ().GetSequenceControl ())
2345  {
2346  i++;
2347  }
2348  if (i != (*it).second.second.end ())
2349  {
2350  guard = (*i)->GetHeader ().GetSequenceControl ();
2351  last = i;
2352  }
2353  }
2354  else
2355  {
2356  guard++;
2357  }
2358  }
2359  else
2360  {
2361  /* go to next packet */
2362  while (i != (*it).second.second.end () && guard == (*i)->GetHeader ().GetSequenceControl ())
2363  {
2364  i++;
2365  }
2366  if (i != (*it).second.second.end ())
2367  {
2368  guard = (*i)->GetHeader ().GetSequenceControl ();
2369  last = i;
2370  }
2371  }
2372  }
2373  (*it).second.second.erase ((*it).second.second.begin (), i);
2374  }
2375 }
2376 
2377 void
2379 {
2380  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2381  if (it != m_bAckAgreements.end ())
2382  {
2383  uint16_t guard = (*it).second.first.GetStartingSequenceControl ();
2384  BufferedPacketI lastComplete = (*it).second.second.begin ();
2385  BufferedPacketI i = (*it).second.second.begin ();
2386  for (; i != (*it).second.second.end () && guard == (*i)->GetHeader ().GetSequenceControl (); i++)
2387  {
2388  if (!(*i)->GetHeader ().IsMoreFragments ())
2389  {
2390  while (lastComplete != i)
2391  {
2392  m_rxCallback (*lastComplete);
2393  lastComplete++;
2394  }
2395  m_rxCallback (*lastComplete);
2396  lastComplete++;
2397  }
2398  guard = (*i)->GetHeader ().IsMoreFragments () ? (guard + 1) : ((guard + 16) & 0xfff0);
2399  }
2400  (*it).second.first.SetStartingSequenceControl (guard);
2401  /* All packets already forwarded to WifiMac must be removed from buffer:
2402  [begin (), lastComplete) */
2403  (*it).second.second.erase ((*it).second.second.begin (), lastComplete);
2404  }
2405 }
2406 
2407 void
2408 MacLow::SendBlockAckResponse (const CtrlBAckResponseHeader* blockAck, Mac48Address originator, bool immediate,
2409  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2410 {
2411  NS_LOG_FUNCTION (this);
2412  Ptr<Packet> packet = Create<Packet> ();
2413  packet->AddHeader (*blockAck);
2414 
2415  WifiMacHeader hdr;
2417  hdr.SetAddr1 (originator);
2418  hdr.SetAddr2 (GetAddress ());
2419  hdr.SetDsNotFrom ();
2420  hdr.SetDsNotTo ();
2421  hdr.SetNoRetry ();
2422  hdr.SetNoMoreFragments ();
2423 
2424  WifiTxVector blockAckReqTxVector = GetBlockAckTxVector (originator, blockAckReqTxMode);
2425 
2426  if (immediate)
2427  {
2429  duration -= GetSifs ();
2430  duration -= GetBlockAckDuration (blockAckReqTxVector, blockAck->GetType ());
2431  }
2432  else
2433  {
2434  m_txParams.EnableAck ();
2435  duration += GetSifs ();
2436  duration += GetAckDuration (originator, blockAckReqTxVector);
2437  }
2439 
2440  if (!immediate)
2441  {
2442  StartDataTxTimers (blockAckReqTxVector);
2443  }
2444 
2445  NS_ASSERT (duration.IsPositive ());
2446  hdr.SetDuration (duration);
2447  //here should be present a control about immediate or delayed BlockAck
2448  //for now we assume immediate
2449  SnrTag tag;
2450  tag.Set (rxSnr);
2451  packet->AddPacketTag (tag);
2452  ForwardDown (Create<const WifiPsdu> (packet, hdr), blockAckReqTxVector);
2453 }
2454 
2455 void
2456 MacLow::SendBlockAckAfterAmpdu (uint8_t tid, Mac48Address originator, Time duration, WifiTxVector blockAckReqTxVector, double rxSnr)
2457 {
2458  NS_LOG_FUNCTION (this);
2459  if (!m_phy->IsStateTx () && !m_phy->IsStateRx ())
2460  {
2461  NS_LOG_FUNCTION (this << +tid << originator << duration.As (Time::S) << blockAckReqTxVector << rxSnr);
2462  CtrlBAckResponseHeader blockAck;
2463  uint16_t seqNumber = 0;
2464  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2465  NS_ASSERT (i != m_bAckCaches.end ());
2466  seqNumber = (*i).second.GetWinStart ();
2467 
2468  bool immediate = true;
2469  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2470  blockAck.SetStartingSequence (seqNumber);
2471  blockAck.SetTidInfo (tid);
2472  immediate = (*it).second.first.IsImmediateBlockAck ();
2473  if ((*it).second.first.GetBufferSize () > 64)
2474  {
2475  blockAck.SetType (EXTENDED_COMPRESSED_BLOCK_ACK);
2476  }
2477  else
2478  {
2479  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2480  }
2481  NS_LOG_DEBUG ("Got Implicit block Ack Req with seq " << seqNumber);
2482  (*i).second.FillBlockAckBitmap (&blockAck);
2483 
2484  WifiTxVector blockAckTxVector = GetBlockAckTxVector (originator, blockAckReqTxVector.GetMode ());
2485 
2486  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckTxVector.GetMode (), rxSnr);
2487  }
2488  else
2489  {
2490  NS_LOG_DEBUG ("Skip block ack response!");
2491  }
2492 }
2493 
2494 void
2496  Time duration, WifiMode blockAckReqTxMode, double rxSnr)
2497 {
2498  NS_LOG_FUNCTION (this);
2499  CtrlBAckResponseHeader blockAck;
2500  uint8_t tid = 0;
2501  bool immediate = false;
2502  if (!reqHdr.IsMultiTid ())
2503  {
2504  tid = reqHdr.GetTidInfo ();
2505  AgreementsI it = m_bAckAgreements.find (std::make_pair (originator, tid));
2506  if (it != m_bAckAgreements.end ())
2507  {
2508  blockAck.SetStartingSequence (reqHdr.GetStartingSequence ());
2509  blockAck.SetTidInfo (tid);
2510  immediate = (*it).second.first.IsImmediateBlockAck ();
2511  if (reqHdr.IsBasic ())
2512  {
2513  blockAck.SetType (BASIC_BLOCK_ACK);
2514  }
2515  else if (reqHdr.IsCompressed ())
2516  {
2517  blockAck.SetType (COMPRESSED_BLOCK_ACK);
2518  }
2519  else if (reqHdr.IsExtendedCompressed ())
2520  {
2522  }
2523  BlockAckCachesI i = m_bAckCaches.find (std::make_pair (originator, tid));
2524  NS_ASSERT (i != m_bAckCaches.end ());
2525  (*i).second.FillBlockAckBitmap (&blockAck);
2526  NS_LOG_DEBUG ("Got block Ack Req with seq " << reqHdr.GetStartingSequence ());
2527 
2531  {
2532  /* All packets with smaller sequence than starting sequence control must be passed up to WifiMac
2533  * See 9.10.3 in IEEE 802.11e standard.
2534  */
2536  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2537  }
2538  else
2539  {
2540  if (!QosUtilsIsOldPacket ((*it).second.first.GetStartingSequence (), reqHdr.GetStartingSequence ()))
2541  {
2542  (*it).second.first.SetStartingSequence (reqHdr.GetStartingSequence ());
2544  RxCompleteBufferedPacketsUntilFirstLost (originator, tid);
2545  }
2546  }
2547  }
2548  else
2549  {
2550  NS_LOG_DEBUG ("there's not a valid block ack agreement with " << originator);
2551  }
2552  }
2553  else
2554  {
2555  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
2556  }
2557  SendBlockAckResponse (&blockAck, originator, immediate, duration, blockAckReqTxMode, rxSnr);
2558 }
2559 
2560 void
2562 {
2563  if (agreement.GetTimeout () != 0)
2564  {
2565  NS_ASSERT (agreement.m_inactivityEvent.IsRunning ());
2566  agreement.m_inactivityEvent.Cancel ();
2567  Time timeout = MicroSeconds (1024 * agreement.GetTimeout ());
2568  AcIndex ac = QosUtilsMapTidToAc (agreement.GetTid ());
2571  m_edca[ac], agreement.GetPeer (),
2572  agreement.GetTid (), false);
2573  }
2574 }
2575 
2576 void
2578 {
2579  m_edca.insert (std::make_pair (ac, edca));
2580 }
2581 
2582 void
2583 MacLow::DeaggregateAmpduAndReceive (Ptr<WifiPsdu> psdu, double rxSnr, WifiTxVector txVector, std::vector<bool> statusPerMpdu)
2584 {
2585  NS_LOG_FUNCTION (this);
2586  bool normalAck = false;
2587  bool ampduSubframe = false; //flag indicating the packet belongs to an A-MPDU and is not a VHT/HE single MPDU
2588  if (txVector.IsAggregation ())
2589  {
2590  NS_ASSERT (psdu->IsAggregate ());
2591  ampduSubframe = true;
2592  auto n = psdu->begin ();
2593  auto status = statusPerMpdu.begin ();
2594  NS_ABORT_MSG_IF (psdu->GetNMpdus () != statusPerMpdu.size (), "Should have one receive status per MPDU");
2595 
2596  WifiMacHeader firsthdr = (*n)->GetHeader ();
2597  NS_LOG_DEBUG ("duration/id=" << firsthdr.GetDuration ());
2598  NotifyNav ((*n)->GetPacket (), firsthdr);
2599 
2600  if (firsthdr.GetAddr1 () == m_self)
2601  {
2602  //Iterate over all MPDUs and notify reception only if status OK
2603  for (; n != psdu->end (); ++n, ++status)
2604  {
2605  firsthdr = (*n)->GetHeader ();
2606  NS_ABORT_MSG_IF (firsthdr.GetAddr1 () != m_self, "All MPDUs of A-MPDU should have the same destination address");
2607  if (*status) //PER and thus CRC check succeeded
2608  {
2609  if (psdu->IsSingle ())
2610  {
2611  //If the MPDU is sent as a VHT/HE single MPDU (EOF=1 in A-MPDU subframe header), then the responder sends an Ack.
2612  NS_LOG_DEBUG ("Receive S-MPDU");
2613  ampduSubframe = false;
2614  }
2615  else if (!m_sendAckEvent.IsRunning () && firsthdr.IsQosAck ()) // Implicit BAR Ack Policy
2616  {
2619  firsthdr.GetQosTid (),
2620  firsthdr.GetAddr2 (),
2621  firsthdr.GetDuration (),
2622  txVector, rxSnr);
2623  }
2624 
2625  if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ())
2626  {
2627  ReceiveOk ((*n), rxSnr, txVector, ampduSubframe);
2628  }
2629  else if (firsthdr.IsData () || firsthdr.IsQosData ())
2630  {
2631  NS_LOG_DEBUG ("Deaggregate packet from " << firsthdr.GetAddr2 () << " with sequence=" << firsthdr.GetSequenceNumber ());
2632  ReceiveOk ((*n), rxSnr, txVector, ampduSubframe);
2633  if (firsthdr.IsQosAck ())
2634  {
2635  NS_LOG_DEBUG ("Normal Ack");
2636  normalAck = true;
2637  }
2638  }
2639  else
2640  {
2641  NS_FATAL_ERROR ("Received A-MPDU with invalid first MPDU type");
2642  }
2643 
2644  if (!psdu->IsSingle ())
2645  {
2646  if (normalAck)
2647  {
2648  //send BlockAck
2649  if (firsthdr.IsBlockAckReq ())
2650  {
2651  NS_FATAL_ERROR ("Sending a BlockAckReq with QosPolicy equal to Normal Ack");
2652  }
2653  uint8_t tid = firsthdr.GetQosTid ();
2654  AgreementsI it = m_bAckAgreements.find (std::make_pair (firsthdr.GetAddr2 (), tid));
2655  if (it != m_bAckAgreements.end ())
2656  {
2657  /* See section 11.5.3 in IEEE 802.11 for the definition of this timer */
2658  ResetBlockAckInactivityTimerIfNeeded (it->second.first);
2659  NS_LOG_DEBUG ("rx A-MPDU/sendImmediateBlockAck from=" << firsthdr.GetAddr2 ());
2661  }
2662  else
2663  {
2664  NS_LOG_DEBUG ("There's not a valid agreement for this block ack request.");
2665  }
2666  }
2667  }
2668  }
2669  }
2670  }
2671  }
2672  else
2673  {
2674  /* Simple MPDU */
2675  NS_ASSERT (!psdu->IsAggregate ());
2676  ReceiveOk ((*psdu->begin ()), rxSnr, txVector, ampduSubframe);
2677  }
2678 }
2679 
2680 Time
2682 {
2683  NS_LOG_FUNCTION (this);
2685  NS_ASSERT (remainingCfpDuration.IsPositive ());
2686  return remainingCfpDuration;
2687 }
2688 
2689 bool
2691 {
2693 }
2694 
2695 bool
2697 {
2698  NS_LOG_FUNCTION (this);
2699  if (!IsCfPeriod ())
2700  {
2701  return false;
2702  }
2703  NS_ASSERT (GetRemainingCfpDuration ().IsPositive ());
2704  WifiMacHeader hdr;
2705  hdr.SetType (WIFI_MAC_DATA);
2706  WifiMacTrailer fcs;
2707  uint32_t maxMacFrameSize = MAX_MSDU_SIZE + hdr.GetSerializedSize () + fcs.GetSerializedSize ();
2709  return ((GetRemainingCfpDuration () - nextTransmission).IsPositive ());
2710 }
2711 
2712 } //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:2133
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void Set(double snr)
Set the SNR to the given value.
Definition: snr-tag.cc:83
Time GetRifs(void) const
Return Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:439
void ScheduleBar(Ptr< const WifiMacQueueItem > bar, bool skipIfNoDataQueued=false)
Definition: qos-txop.cc:167
bool IsCfEnd(void) const
Return true if the header is a CF-End header.
void SetPifs(Time pifs)
Set PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:373
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
bool IsStateOff(void) const
Definition: wifi-phy.cc:4066
Ptr< const WifiMacQueueItem > PeekNextFrame(uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast())
Peek the next frame to transmit to the given receiver and of the given TID from the block ack manager...
Definition: qos-txop.cc:253
bool GetRifsPermitted(void) const
Return whether the device can use RIFS.
bool IsAggregation(void) const
Checks whether the PSDU contains A-MPDU.
uint16_t GetTimeout(void) const
Return the timeout.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
EventId m_navCounterResetCtsMissed
Event to reset NAV when CTS is not received.
Definition: mac-low.h:929
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:911
microsecond
Definition: nstime.h:116
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:2561
EventId m_blockAckTimeoutEvent
BlockAck timeout event.
Definition: mac-low.h:922
Time CalculateOverallTxTime(Ptr< const Packet > packet, const WifiMacHeader *hdr, const MacLowTransmissionParameters &params, uint32_t fragmentSize=0) const
Definition: mac-low.cc:1517
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:3994
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:2495
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
bool ReceiveMpdu(Ptr< WifiMacQueueItem > mpdu)
Definition: mac-low.cc:2189
void SetDuration(Time duration)
Set the Duration/ID field with the given duration (Time object).
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
static Time Min()
Minimum representable Time.
Definition: nstime.h:271
void SetPromisc(void)
Enable promiscuous mode.
Definition: mac-low.cc:403
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:1616
bool GetShortGuardInterval(void) const
Return whether short guard interval is supported.
Definition: wifi-phy.cc:668
Ptr< Txop > m_currentTxop
Current TXOP.
Definition: mac-low.h:932
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
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:209
Ptr< QosTxop > GetEdca(uint8_t tid) const
Definition: mac-low.cc:279
Ptr< MsduAggregator > m_msduAggregator
A-MSDU aggregator.
Definition: mac-low.h:918
Time m_pifs
PCF Interframe Space (PIFS) duration.
Definition: mac-low.h:941
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:238
bool DoNavStartNow(Time duration)
Start NAV with the given duration.
Definition: mac-low.cc:1628
uint32_t GetSize(void) const
Return the size of the WifiMacHeader in octets.
void SetSifs(Time sifs)
Set Short Interframe Space (SIFS) of this MacLow.
Definition: mac-low.cc:361
void NotifySwitchingStart(Time duration)
Definition: mac-low.cc:92
std::pair< Mac48Address, uint8_t > AgreementKey
agreement key typedef
Definition: mac-low.h:963
void SetNoMoreFragments(void)
Un-set the More Fragment bit in the Frame Control Field.
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:464
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:1539
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:756
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:1287
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:2009
void NotifyOffNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:808
double ToDouble(enum Unit unit) const
Get the Time value expressed in a particular unit.
Definition: nstime.h:511
void NotifySleepNow(void)
This method is typically invoked by the PhyMacLowListener to notify the MAC layer that the device has...
Definition: mac-low.cc:793
void NotifyNav(Ptr< const Packet > packet, const WifiMacHeader &hdr)
Notify NAV function.
Definition: mac-low.cc:1571
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:457
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:162
bool QosUtilsIsOldPacket(uint16_t startingSeq, uint16_t seqNumber)
This function checks if packet with sequence number seqNumber is an "old" packet. ...
Definition: qos-utils.cc:84
bool IsStrictlyPositive(void) const
Definition: nstime.h:314
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:181
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:743
uint16_t GetBufferSize(void) const
Return the buffer size.
VHT PHY (Clause 22)
Definition: wifi-mode.h:60
void ReportDataOk(Mac48Address address, const WifiMacHeader *header, double ackSnr, WifiMode ackMode, double dataSnr, WifiTxVector dataTxVector, uint32_t packetSize)
Should be invoked whenever we receive the ACK associated to a data packet we just sent...
TimeWithUnit As(const enum Unit unit) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:389
WifiTxVector GetRtsTxVector(Ptr< const WifiMacQueueItem > item) const
Return a TXVECTOR for the RTS frame given the destination.
Definition: mac-low.cc:1275
Mac48Address m_bssid
BSSID address (Mac48Address)
Definition: mac-low.h:935
ns3::Time timeout
WifiPreamble GetPreambleForTransmission(WifiModulationClass modulation, bool useShortPreamble, bool useGreenfield)
Return the preamble to be used for the transmission.
Definition: wifi-utils.cc:128
const char * GetTypeString(void) const
Return a string corresponds to the header type.
bool IsCfPoll(void) const
Return true if the Type/Subtype is one of the possible CF-Poll headers.
uint8_t GetNBasicMcs(void) const
Return the number of basic MCS index.
EventId m_sendCtsEvent
Event to send CTS.
Definition: mac-low.h:924
MacLowRxCallback m_rxCallback
Callback to pass packet up.
Definition: mac-low.h:896
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:903
EventId m_sendAckEvent
Event to send Ack.
Definition: mac-low.h:925
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
WifiMode GetControlAnswerMode(WifiMode reqMode) const
Get control answer mode function.
Definition: mac-low.cc:1315
void NotifyAckTimeoutResetNow(void)
Notify ChannelAccessManager that Ack timer should be reset.
Definition: mac-low.cc:1655
Time m_cfpMaxDuration
CFP max duration.
Definition: mac-low.h:945
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:1556
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:961
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
bool IsBlockAck(void) const
Return true if the header is a BlockAck header.
virtual void GotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, double dataSnr, WifiTxVector dataTxVector)
Event handler when a BlockAck is received.
Definition: txop.cc:873
bool IsMandatory(void) const
Definition: wifi-mode.cc:434
void SetCtsToSelfSupported(bool enable)
Enable or disable CTS-to-self capability.
Definition: mac-low.cc:349
bool expectCfAck
Flag used for PCF to indicate whether a CF-Ack should be expected.
Definition: mac-low.h:904
QueueEdcas m_edca
EDCA queues.
Definition: mac-low.h:976
void NormalAckTimeout(void)
Event handler when normal Ack timeout occurs.
Definition: mac-low.cc:1788
void SetBasicBlockAckTimeout(Time blockAckTimeout)
Set Basic BlockAck timeout of this MacLow.
Definition: mac-low.cc:337
phy
Definition: third.py:93
BlockAckCaches m_bAckCaches
block ack caches
Definition: mac-low.h:973
uint16_t GetChannelWidth(void) const
Definition: wifi-phy.cc:1392
Ptr< WifiMac > m_mac
Pointer to WifiMac (to fetch configuration)
Definition: mac-low.h:894
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:3988
static Time CalculateTxDuration(uint32_t size, WifiTxVector txVector, uint16_t frequency)
Definition: wifi-phy.cc:2417
bool IsPromisc(void) const
Check if MacLow is operating in promiscuous mode.
Definition: mac-low.cc:475
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:979
bool GetShortPreambleEnabled(void) const
Return whether the device uses short PHY preambles.
void DestroyBlockAckAgreement(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2299
Time m_lastNavDuration
The duration of the latest NAV.
Definition: mac-low.h:948
bool IsImmediateBlockAck(void) const
Return whether the Block Ack policy is immediate Block Ack.
void SetCfpMaxDuration(Time duration)
Definition: mac-low.cc:391
Time GetCtsDuration(WifiTxVector ctsTxVector) const
Return the time required to transmit the CTS (including preamble and FCS).
Definition: mac-low.cc:1268
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:652
void SendCtsToSelf(void)
Send CTS for a CTS-to-self mechanism.
Definition: mac-low.cc:2015
bool m_ctsToSelfSupported
Flag whether CTS-to-self is supported.
Definition: mac-low.h:978
void SendAckAfterData(Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
Send Ack after receiving Data.
Definition: mac-low.cc:2159
Mac48Address GetAddress(void) const
Return the MAC address of this MacLow.
Definition: mac-low.cc:409
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:493
#define max(a, b)
Definition: 80211b.c:43
void CreateBlockAckAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address originator, uint16_t startingSeq)
Definition: mac-low.cc:2257
Time m_lastBeacon
The time when the last beacon frame transmission started.
Definition: mac-low.h:951
bool IsQosNoAck(void) const
Return if the QoS Ack policy is No Ack.
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
Time GetCompressedBlockAckTimeout(void) const
Return Compressed BlockAck timeout of this MacLow.
Definition: mac-low.cc:427
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:1086
receive notifications about PHY events.
void CtsTimeout(void)
Event handler when CTS timeout occurs.
Definition: mac-low.cc:1766
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:2583
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:433
void EndTxNoAck(void)
A transmission that does not require an Ack has completed.
Definition: mac-low.cc:2140
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:2456
std::map< AgreementKey, BlockAckCache >::iterator BlockAckCachesI
block ack caches iterator typedef
Definition: mac-low.h:970
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:2690
void SetAckTimeout(Time ackTimeout)
Set Ack timeout of this MacLow.
Definition: mac-low.cc:331
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:71
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:32
bool StoreMpduIfNeeded(Ptr< WifiMacQueueItem > mpdu)
Definition: mac-low.cc:2230
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
bool IsCts(void) const
Return true if the header is a CTS header.
WifiMode GetMode(void) const
HT PHY (Clause 20)
Definition: wifi-mode.h:58
Ptr< WifiRemoteStationManager > m_stationManager
Pointer to WifiRemoteStationManager (rate control)
Definition: mac-low.h:895
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:2084
void RegisterEdcaForAc(AcIndex ac, Ptr< QosTxop > edca)
Definition: mac-low.cc:2577
Agreements m_bAckAgreements
block ack agreements
Definition: mac-low.h:972
void RegisterChannelAccessManager(Ptr< ChannelAccessManager > channelAccessManager)
Definition: mac-low.cc:487
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:1281
virtual bool IsQosTxop() const
Check for QoS TXOP.
Definition: txop.cc:861
void NotifySwitchingStartNow(Time duration)
Definition: mac-low.cc:777
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:463
void NotifyOff(void)
Notify listeners that we went to switch off.
Definition: mac-low.cc:100
Time GetCfpMaxDuration(void) const
Definition: mac-low.cc:469
Time m_slotTime
Slot duration.
Definition: mac-low.h:940
#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:1473
WifiMode GetDefaultMode(void) const
Return the default transmission mode.
void RxStartIndication(WifiTxVector txVector, Time psduDuration)
Definition: mac-low.cc:714
Mac48Address GetPeer(void) const
Return the peer address.
bool m_promisc
Flag if the device is operating in promiscuous mode.
Definition: mac-low.h:954
void NotifyRxStart(Time duration)
Definition: mac-low.cc:77
void SetNss(uint8_t nss)
Sets the number of Nss refer to IEEE 802.11n Table 20-28 for explanation and range.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
void CancelAllEvents(void)
Cancel all scheduled events.
Definition: mac-low.cc:201
WifiTxVector GetCtsTxVector(Mac48Address to, WifiMode rtsTxMode) const
Return a TXVECTOR for the CTS frame given the destination and the mode of the RTS used by the sender...
Definition: mac-low.cc:1457
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
void BlockAckTimeout(void)
Event handler when BlockAck timeout occurs.
Definition: mac-low.cc:1801
void NotifyCtsTimeoutStartNow(Time duration)
Notify ChannelAccessManager that CTS timer should be started for the given duration.
Definition: mac-low.cc:1664
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.
Time GetAckTimeout(void) const
Return Ack timeout of this MacLow.
Definition: mac-low.cc:415
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Time GetRemainingCfpDuration(void) const
Definition: mac-low.cc:2681
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:397
Time GetBasicBlockAckTimeout(void) const
Return Basic BlockAck timeout of this MacLow.
Definition: mac-low.cc:421
uint16_t GetFrequency(void) const
Definition: wifi-phy.cc:1372
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
EventId m_waitIfsEvent
Wait for IFS event.
Definition: mac-low.h:927
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:921
bool IsHigherCodeRate(WifiMode mode) const
Definition: wifi-mode.cc:558
void StartDataTxTimers(WifiTxVector dataTxVector)
Start a Data timer by scheduling appropriate Ack timeout.
Definition: mac-low.cc:1854
#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:944
uint16_t GetChannelWidthForTransmission(WifiMode mode, uint16_t maxSupportedChannelWidth)
Return the channel width that corresponds to the selected mode (instead of letting the PHY&#39;s default ...
Definition: wifi-utils.cc:109
bool UseGreenfieldForDestination(Mac48Address dest) const
bool IsMultiTid(void) const
Check if the current Ack Policy has Multi-TID Block Ack.
bool IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
Definition: wifi-utils.cc:225
an EUI-48 address
Definition: mac48-address.h:43
bool IsBasic(void) const
Check if the current Ack Policy is Basic Block Ack (i.e.
Time m_cfpForeshortening
The delay the current CF period should be foreshortened.
Definition: mac-low.h:952
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:964
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:2408
Time GetAckDuration(WifiTxVector ackTxVector) const
Return the time required to transmit the Ack (including preamble and FCS).
Definition: mac-low.cc:1238
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
Time m_ackTimeout
Ack timeout duration.
Definition: mac-low.h:936
bool IsAllowedControlAnswerModulationClass(WifiModulationClass modClassReq, WifiModulationClass modClassAnswer)
Return whether the modulation class of the selected mode for the control answer frame is allowed...
Definition: wifi-utils.cc:158
bool IsGroup(void) const
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc: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:923
void RxCompleteBufferedPacketsWithSmallerSequence(uint16_t seq, Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2315
void SendCtsAfterRts(Mac48Address source, Time duration, WifiTxVector rtsTxVector, double rtsSnr)
Send CTS after receiving RTS.
Definition: mac-low.cc:2054
uint32_t GetBlockAckRequestSize(BlockAckType type)
Return the total BlockAckRequest size (including FCS trailer).
Definition: wifi-utils.cc:199
Ptr< MsduAggregator > GetMsduAggregator(void) const
Returns the aggregator used to construct A-MSDU subframes.
Definition: mac-low.cc: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:1255
Time m_basicBlockAckTimeout
Basic BlockAck timeout duration.
Definition: mac-low.h:937
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:355
Time m_sifs
Short Interframe Space (SIFS) duration.
Definition: mac-low.h:939
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetBeaconInterval(Time interval)
Definition: mac-low.cc:385
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:3976
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:217
Time m_lastNavStart
The time when the latest NAV started.
Definition: mac-low.h:947
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:905
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:458
WifiMode GetMode(uint8_t mode) const
The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used (e.g., by a WifiRemoteStationManager...
Definition: wifi-phy.cc:3982
bool IsQosBlockAck(void) const
Return if the QoS Ack policy is Block Ack.
EventId m_sendDataEvent
Event to send Data.
Definition: mac-low.h:926
bool IsStateTx(void) const
Definition: wifi-phy.cc:4048
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:933
void SetRifs(Time rifs)
Set Reduced Interframe Space (RIFS) of this MacLow.
Definition: mac-low.cc:379
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:1511
bool IsMgt(void) const
Return true if the Type is Management.
WifiModulationClass
This enumeration defines the modulation classes per (Table 9-4 "Modulation classes"; IEEE 802...
Definition: wifi-mode.h:36
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
Time GetPpduMaxTime(WifiPreamble preamble)
Get the maximum PPDU duration (see Section 10.14 of 802.11-2016) for the PHY layers defining the aPPD...
Definition: wifi-utils.cc:254
void ReceiveOk(Ptr< WifiMacQueueItem > mpdu, double rxSnr, WifiTxVector txVector, bool ampduSubframe)
Definition: mac-low.cc:823
Mac48Address m_self
Address of this MacLow (Mac48Address)
Definition: mac-low.h:934
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:1489
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:863
uint32_t QosUtilsMapSeqControlToUniqueInteger(uint16_t seqControl, uint16_t endSequence)
Next function is useful to correctly sort buffered packets under block ack.
Definition: qos-utils.cc:73
void NotifyAckTimeoutStartNow(Time duration)
Notify ChannelAccessManager that Ack timer should be started for the given duration.
Definition: mac-low.cc:1646
bool CanTransmitNextCfFrame(void) const
This function decides if a CF frame can be transmitted in the current CFP.
Definition: mac-low.cc:2696
void SetSlotTime(Time slotTime)
Set slot duration of this MacLow.
Definition: mac-low.cc:367
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
Definition: nstime.h:304
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:870
Implement the header for management frames of type Add Block Ack response.
Definition: mgt-headers.h:1135
Time m_cfpStart
The time when the latest CF period started.
Definition: mac-low.h:950
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:189
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1062
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:967
uint32_t GetSerializedSize(void) const
EventId m_endTxNoAckEvent
Event for finishing transmission that does not require Ack.
Definition: mac-low.h:928
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
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:1245
WifiTxVector GetRtsTxVector(Mac48Address address)
CfAckInfo m_cfAckInfo
Info about piggyback Acks used in PCF.
Definition: mac-low.h:981
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:2541
void SetImmediateBlockAck(void)
Set block ack policy to immediate Ack.
bool IsRts(void) const
Return true if the header is a RTS header.
void DisableNextData(void)
Do not attempt to send data burst after current transmission.
BlockAckType GetType(void) const
Return the block ack type ID.
void SendDataPacket(void)
Send Data packet, which can be Data-Ack or RTS-CTS-Data-Ack transaction.
Definition: mac-low.cc:1919
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:1078
Time GetPifs(void) const
Return PCF Interframe Space (PIFS) of this MacLow.
Definition: mac-low.cc:451
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:1216
void ForwardDown(Ptr< const WifiPsdu > psdu, WifiTxVector txVector)
Forward a PSDU down to WifiPhy for transmission.
Definition: mac-low.cc:1682
second
Definition: nstime.h:114
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:2126
void SetRxCallback(Callback< void, Ptr< WifiMacQueueItem >> callback)
Definition: mac-low.cc:481
PhyMacLowListener(ns3::MacLow *macLow)
Create a PhyMacLowListener for the given MacLow.
Definition: mac-low.cc:70
Time GetBeaconInterval(void) const
Definition: mac-low.cc:463
Time m_compressedBlockAckTimeout
Compressed BlockAck timeout duration.
Definition: mac-low.h:938
void CfPollTimeout(void)
Event handler when CF-Poll timeout occurs.
Definition: mac-low.cc:1748
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:1673
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:931
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:445
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:1505
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
a unique identifier for an interface.
Definition: type-id.h:58
bool IsHigherDataRate(WifiMode mode) const
Definition: wifi-mode.cc:578
BlockAckCache cache.
uint16_t GetStartingSequenceControl(void) const
Return the starting sequence control.
bool NeedCtsToSelf(void) const
Check if CTS-to-self mechanism should be used for the current packet.
Definition: mac-low.cc:645
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:4042
Time m_rifs
Reduced Interframe Space (RIFS) duration.
Definition: mac-low.h:942
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:38
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
Introspection did not find any typical Config paths.
Definition: snr-tag.h:34
HE PHY (Clause 26)
Definition: wifi-mode.h:62
virtual ~MacLow()
Definition: mac-low.cc:142
Ptr< MpduAggregator > m_mpduAggregator
A-MPDU aggregator.
Definition: mac-low.h:919
Ptr< WifiPhy > m_phy
Pointer to WifiPhy (actually send/receives frames)
Definition: mac-low.h:893
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:119
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > manager)
Set up WifiRemoteStationManager associated with this MacLow.
Definition: mac-low.cc:293
Implements the IEEE 802.11 MAC header.
bool IsNegative(void) const
Definition: nstime.h:299
void SetCompressedBlockAckTimeout(Time blockAckTimeout)
Set Compressed BlockAck timeout of this MacLow.
Definition: mac-low.cc:343
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:956
ChannelAccessManagers m_channelAccessManagers
List of ChannelAccessManager.
Definition: mac-low.h:916
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:1811
BlockAckType
The different block ack policies.
static Time CalculatePhyPreambleAndHeaderDuration(WifiTxVector txVector)
Definition: wifi-phy.cc:2403
void RxCompleteBufferedPacketsUntilFirstLost(Mac48Address originator, uint8_t tid)
Definition: mac-low.cc:2378
Time GetGuardInterval(void) const
Definition: wifi-phy.cc:700
Time GetTxopLimit(void) const
Return the TXOP limit.
Definition: txop.cc:303