A Discrete-Event Network Simulator
API
qos-frame-exchange-manager.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Stefano Avallone <stavallo@unina.it>
18  */
19 
21 
22 #include "ap-wifi-mac.h"
23 #include "wifi-mac-queue.h"
24 #include "wifi-mac-trailer.h"
25 
26 #include "ns3/abort.h"
27 #include "ns3/log.h"
28 
29 #undef NS_LOG_APPEND_CONTEXT
30 #define NS_LOG_APPEND_CONTEXT std::clog << "[link=" << +m_linkId << "][mac=" << m_self << "] "
31 
32 namespace ns3
33 {
34 
35 NS_LOG_COMPONENT_DEFINE("QosFrameExchangeManager");
36 
37 NS_OBJECT_ENSURE_REGISTERED(QosFrameExchangeManager);
38 
39 TypeId
41 {
42  static TypeId tid =
43  TypeId("ns3::QosFrameExchangeManager")
45  .AddConstructor<QosFrameExchangeManager>()
46  .SetGroupName("Wifi")
47  .AddAttribute("PifsRecovery",
48  "Perform a PIFS recovery as a response to transmission failure "
49  "within a TXOP",
50  BooleanValue(true),
53  .AddAttribute("SetQueueSize",
54  "Whether to set the Queue Size subfield of the QoS Control field "
55  "of QoS data frames sent by non-AP stations",
56  BooleanValue(false),
59  return tid;
60 }
61 
63  : m_initialFrame(false)
64 {
65  NS_LOG_FUNCTION(this);
66 }
67 
69 {
71 }
72 
73 void
75 {
76  NS_LOG_FUNCTION(this);
77  m_edca = nullptr;
78  m_edcaBackingOff = nullptr;
81 }
82 
83 bool
85 {
86  NS_LOG_FUNCTION(this);
89 
90  WifiMacHeader cfEnd;
92  cfEnd.SetDsNotFrom();
93  cfEnd.SetDsNotTo();
94  cfEnd.SetNoRetry();
95  cfEnd.SetNoMoreFragments();
96  cfEnd.SetDuration(Seconds(0));
98  cfEnd.SetAddr2(m_self);
99 
101 
102  Time txDuration = m_phy->CalculateTxDuration(cfEnd.GetSize() + WIFI_MAC_FCS_LENGTH,
103  cfEndTxVector,
104  m_phy->GetPhyBand());
105 
106  // Send the CF-End frame if the remaining duration is long enough to transmit this frame
107  if (m_edca->GetRemainingTxop(m_linkId) > txDuration)
108  {
109  NS_LOG_DEBUG("Send CF-End frame");
110  m_phy->Send(Create<WifiPsdu>(Create<Packet>(), cfEnd), cfEndTxVector);
112  return true;
113  }
114 
116  m_edca = nullptr;
117  return false;
118 }
119 
120 void
122 {
123  NS_LOG_FUNCTION(this);
124  NS_ASSERT(m_edca);
126 
127  // Release the channel if it has not been idle for the last PIFS interval
130  {
132  m_edca = nullptr;
133  }
134  else
135  {
136  // the txopDuration parameter is unused because we are not starting a new TXOP
138  }
139 }
140 
141 void
143 {
144  NS_LOG_FUNCTION(this);
146  NS_ASSERT(m_edca);
147 
148  NS_LOG_DEBUG("Cancel PIFS recovery being attempted by EDCAF " << m_edca);
151 }
152 
153 bool
155 {
156  NS_LOG_FUNCTION(this << edca << allowedWidth);
157 
159  {
160  // Another AC (having AIFS=1 or lower, if the user changed the default settings)
161  // gained channel access while performing PIFS recovery. Abort PIFS recovery
163  }
164 
165  // TODO This will become an assert once no Txop is installed on a QoS station
166  if (!edca->IsQosTxop())
167  {
168  m_edca = nullptr;
169  return FrameExchangeManager::StartTransmission(edca, allowedWidth);
170  }
171 
172  m_allowedWidth = allowedWidth;
173  auto qosTxop = StaticCast<QosTxop>(edca);
174  return StartTransmission(qosTxop, qosTxop->GetTxopLimit(m_linkId));
175 }
176 
177 bool
179 {
180  NS_LOG_FUNCTION(this << edca << txopDuration);
181 
183  {
184  // Another AC (having AIFS=1 or lower, if the user changed the default settings)
185  // gained channel access while performing PIFS recovery. Abort PIFS recovery
187  }
188 
189  if (m_txTimer.IsRunning())
190  {
191  m_txTimer.Cancel();
192  }
193  m_dcf = edca;
194  m_edca = edca;
195 
196  // We check if this EDCAF invoked the backoff procedure (without terminating
197  // the TXOP) because the transmission of a non-initial frame of a TXOP failed
198  bool backingOff = (m_edcaBackingOff == m_edca);
199 
200  if (backingOff)
201  {
206 
207  // clear the member variable
208  m_edcaBackingOff = nullptr;
209  }
210 
212  {
213  // TXOP limit is not null. We have to check if this EDCAF is starting a
214  // new TXOP. This includes the case when the transmission of a non-initial
215  // frame of a TXOP failed and backoff was invoked without terminating the
216  // TXOP. In such a case, we assume that a new TXOP is being started if it
217  // elapsed more than TXOPlimit since the start of the paused TXOP. Note
218  // that GetRemainingTxop returns 0 iff Now - TXOPstart >= TXOPlimit
219  if (!m_edca->IsTxopStarted(m_linkId) ||
220  (backingOff && m_edca->GetRemainingTxop(m_linkId).IsZero()))
221  {
222  // starting a new TXOP
223  m_edca->NotifyChannelAccessed(m_linkId, txopDuration);
224 
225  if (StartFrameExchange(m_edca, txopDuration, true))
226  {
227  m_initialFrame = true;
228  return true;
229  }
230 
231  // TXOP not even started, return false
232  NS_LOG_DEBUG("No frame transmitted");
234  m_edca = nullptr;
235  return false;
236  }
237 
238  // We are continuing a TXOP, check if we can transmit another frame
240 
242  {
243  NS_LOG_DEBUG("Not enough remaining TXOP time");
244  return SendCfEndIfNeeded();
245  }
246 
247  return true;
248  }
249 
250  // we get here if TXOP limit is null
251  m_initialFrame = true;
252 
253  if (StartFrameExchange(m_edca, Time::Min(), true))
254  {
256  return true;
257  }
258 
259  NS_LOG_DEBUG("No frame transmitted");
261  m_edca = nullptr;
262  return false;
263 }
264 
265 bool
267  Time availableTime,
268  bool initialFrame)
269 {
270  NS_LOG_FUNCTION(this << edca << availableTime << initialFrame);
271 
272  Ptr<WifiMpdu> mpdu = edca->PeekNextMpdu(m_linkId);
273 
274  // Even though channel access is requested when the queue is not empty, at
275  // the time channel access is granted the lifetime of the packet might be
276  // expired and the queue might be empty.
277  if (!mpdu)
278  {
279  NS_LOG_DEBUG("Queue empty");
280  return false;
281  }
282 
283  mpdu = CreateAliasIfNeeded(mpdu);
284  WifiTxParameters txParams;
285  txParams.m_txVector =
287 
288  Ptr<WifiMpdu> item = edca->GetNextMpdu(m_linkId, mpdu, txParams, availableTime, initialFrame);
289 
290  if (!item)
291  {
292  NS_LOG_DEBUG("Not enough time to transmit a frame");
293  return false;
294  }
295 
296  NS_ASSERT_MSG(!item->GetHeader().IsQosData() || !item->GetHeader().IsQosAmsdu(),
297  "We should not get an A-MSDU here");
298 
299  // check if the MSDU needs to be fragmented
300  item = GetFirstFragmentIfNeeded(item);
301 
302  // update the protection method if the frame was fragmented
303  if (item->IsFragment() && item->GetSize() != mpdu->GetSize())
304  {
305  WifiTxParameters fragmentTxParams;
306  fragmentTxParams.m_txVector = txParams.m_txVector;
307  txParams.m_protection = GetProtectionManager()->TryAddMpdu(item, fragmentTxParams);
308  NS_ASSERT(txParams.m_protection);
309  }
310 
311  SendMpduWithProtection(item, txParams);
312 
313  return true;
314 }
315 
318 {
319  return mpdu;
320 }
321 
322 bool
324  WifiTxParameters& txParams,
325  Time availableTime) const
326 {
327  NS_ASSERT(mpdu);
328  NS_LOG_FUNCTION(this << *mpdu << &txParams << availableTime);
329 
330  // check if adding the given MPDU requires a different protection method
331  Time protectionTime = Time::Min(); // uninitialized
332  if (txParams.m_protection)
333  {
334  protectionTime = txParams.m_protection->protectionTime;
335  }
336 
337  std::unique_ptr<WifiProtection> protection;
338  protection = GetProtectionManager()->TryAddMpdu(mpdu, txParams);
339  bool protectionSwapped = false;
340 
341  if (protection)
342  {
343  // the protection method has changed, calculate the new protection time
344  CalculateProtectionTime(protection.get());
345  protectionTime = protection->protectionTime;
346  // swap unique pointers, so that the txParams that is passed to the next
347  // call to IsWithinLimitsIfAddMpdu is the most updated one
348  txParams.m_protection.swap(protection);
349  protectionSwapped = true;
350  }
351  NS_ASSERT(protectionTime != Time::Min());
352  NS_LOG_DEBUG("protection time=" << protectionTime);
353 
354  // check if adding the given MPDU requires a different acknowledgment method
355  Time acknowledgmentTime = Time::Min(); // uninitialized
356  if (txParams.m_acknowledgment)
357  {
358  acknowledgmentTime = txParams.m_acknowledgment->acknowledgmentTime;
359  }
360 
361  std::unique_ptr<WifiAcknowledgment> acknowledgment;
362  acknowledgment = GetAckManager()->TryAddMpdu(mpdu, txParams);
363  bool acknowledgmentSwapped = false;
364 
365  if (acknowledgment)
366  {
367  // the acknowledgment method has changed, calculate the new acknowledgment time
368  CalculateAcknowledgmentTime(acknowledgment.get());
369  acknowledgmentTime = acknowledgment->acknowledgmentTime;
370  // swap unique pointers, so that the txParams that is passed to the next
371  // call to IsWithinLimitsIfAddMpdu is the most updated one
372  txParams.m_acknowledgment.swap(acknowledgment);
373  acknowledgmentSwapped = true;
374  }
375  NS_ASSERT(acknowledgmentTime != Time::Min());
376  NS_LOG_DEBUG("acknowledgment time=" << acknowledgmentTime);
377 
378  Time ppduDurationLimit = Time::Min();
379  if (availableTime != Time::Min())
380  {
381  ppduDurationLimit = availableTime - protectionTime - acknowledgmentTime;
382  }
383 
384  if (!IsWithinLimitsIfAddMpdu(mpdu, txParams, ppduDurationLimit))
385  {
386  // adding MPDU failed, restore protection and acknowledgment methods
387  // if they were swapped
388  if (protectionSwapped)
389  {
390  txParams.m_protection.swap(protection);
391  }
392  if (acknowledgmentSwapped)
393  {
394  txParams.m_acknowledgment.swap(acknowledgment);
395  }
396  return false;
397  }
398 
399  // the given MPDU can be added, hence update the txParams
400  txParams.AddMpdu(mpdu);
401  UpdateTxDuration(mpdu->GetHeader().GetAddr1(), txParams);
402 
403  return true;
404 }
405 
406 bool
408  const WifiTxParameters& txParams,
409  Time ppduDurationLimit) const
410 {
411  NS_ASSERT(mpdu);
412  NS_LOG_FUNCTION(this << *mpdu << &txParams << ppduDurationLimit);
413 
414  // A QoS station only has to check that the MPDU transmission time does not
415  // exceed the given limit
416  return IsWithinSizeAndTimeLimits(mpdu->GetSize(),
417  mpdu->GetHeader().GetAddr1(),
418  txParams,
419  ppduDurationLimit);
420 }
421 
422 bool
424  Mac48Address receiver,
425  const WifiTxParameters& txParams,
426  Time ppduDurationLimit) const
427 {
428  NS_LOG_FUNCTION(this << ppduPayloadSize << receiver << &txParams << ppduDurationLimit);
429 
430  if (ppduDurationLimit != Time::Min() && ppduDurationLimit.IsNegative())
431  {
432  NS_LOG_DEBUG("ppduDurationLimit is null or negative, time limit is trivially exceeded");
433  return false;
434  }
435 
436  if (ppduPayloadSize > WifiPhy::GetMaxPsduSize(txParams.m_txVector.GetModulationClass()))
437  {
438  NS_LOG_DEBUG("the frame exceeds the max PSDU size");
439  return false;
440  }
441 
442  // Get the maximum PPDU Duration based on the preamble type
443  Time maxPpduDuration = GetPpduMaxTime(txParams.m_txVector.GetPreambleType());
444 
445  Time txTime = GetTxDuration(ppduPayloadSize, receiver, txParams);
446  NS_LOG_DEBUG("PPDU duration: " << txTime.As(Time::MS));
447 
448  if ((ppduDurationLimit.IsStrictlyPositive() && txTime > ppduDurationLimit) ||
449  (maxPpduDuration.IsStrictlyPositive() && txTime > maxPpduDuration))
450  {
451  NS_LOG_DEBUG(
452  "the frame does not meet the constraint on max PPDU duration or PPDU duration limit");
453  return false;
454  }
455 
456  return true;
457 }
458 
459 Time
461  uint32_t size,
462  const WifiTxParameters& txParams,
463  Ptr<Packet> fragmentedPacket) const
464 {
465  NS_LOG_FUNCTION(this << header << size << &txParams << fragmentedPacket);
466 
467  // TODO This will be removed once no Txop is installed on a QoS station
468  if (!m_edca)
469  {
470  return FrameExchangeManager::GetFrameDurationId(header, size, txParams, fragmentedPacket);
471  }
472 
474  {
475  return FrameExchangeManager::GetFrameDurationId(header, size, txParams, fragmentedPacket);
476  }
477 
478  NS_ASSERT(txParams.m_acknowledgment &&
479  txParams.m_acknowledgment->acknowledgmentTime != Time::Min());
480 
481  // under multiple protection settings, if the TXOP limit is not null, Duration/ID
482  // is set to cover the remaining TXOP time (Sec. 9.2.5.2 of 802.11-2016).
483  // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8
484  // of 802.11-2016)
486  m_phy->CalculateTxDuration(size, txParams.m_txVector, m_phy->GetPhyBand()),
487  txParams.m_acknowledgment->acknowledgmentTime);
488 }
489 
490 Time
492  Time txDuration,
493  Time response) const
494 {
495  NS_LOG_FUNCTION(this << rtsTxVector << txDuration << response);
496 
497  // TODO This will be removed once no Txop is installed on a QoS station
498  if (!m_edca)
499  {
500  return FrameExchangeManager::GetRtsDurationId(rtsTxVector, txDuration, response);
501  }
502 
504  {
505  return FrameExchangeManager::GetRtsDurationId(rtsTxVector, txDuration, response);
506  }
507 
508  // under multiple protection settings, if the TXOP limit is not null, Duration/ID
509  // is set to cover the remaining TXOP time (Sec. 9.2.5.2 of 802.11-2016).
510  // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8
511  // of 802.11-2016)
513  m_phy->CalculateTxDuration(GetRtsSize(), rtsTxVector, m_phy->GetPhyBand()),
514  Seconds(0));
515 }
516 
517 Time
519  Time txDuration,
520  Time response) const
521 {
522  NS_LOG_FUNCTION(this << ctsTxVector << txDuration << response);
523 
524  // TODO This will be removed once no Txop is installed on a QoS station
525  if (!m_edca)
526  {
527  return FrameExchangeManager::GetCtsToSelfDurationId(ctsTxVector, txDuration, response);
528  }
529 
531  {
532  return FrameExchangeManager::GetCtsToSelfDurationId(ctsTxVector, txDuration, response);
533  }
534 
535  // under multiple protection settings, if the TXOP limit is not null, Duration/ID
536  // is set to cover the remaining TXOP time (Sec. 9.2.5.2 of 802.11-2016).
537  // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8
538  // of 802.11-2016)
540  m_phy->CalculateTxDuration(GetCtsSize(), ctsTxVector, m_phy->GetPhyBand()),
541  Seconds(0));
542 }
543 
544 void
546 {
547  NS_LOG_FUNCTION(this << *mpdu << txVector);
548 
549  WifiMacHeader& hdr = mpdu->GetHeader();
550 
551  if (hdr.IsQosData() && m_mac->GetTypeOfStation() == STA &&
552  (m_setQosQueueSize || hdr.IsQosEosp()))
553  {
554  uint8_t tid = hdr.GetQosTid();
555  hdr.SetQosEosp();
556  hdr.SetQosQueueSize(m_mac->GetQosTxop(tid)->GetQosQueueSize(tid, hdr.GetAddr1()));
557  }
559 }
560 
561 void
563 {
564  NS_LOG_DEBUG(this);
565 
566  // TODO This will be removed once no Txop is installed on a QoS station
567  if (!m_edca)
568  {
570  return;
571  }
572 
575  {
576  NS_LOG_DEBUG("Schedule another transmission in a SIFS");
579 
580  // we are continuing a TXOP, hence the txopDuration parameter is unused
581  Simulator::Schedule(m_phy->GetSifs(), fp, this, m_edca, Seconds(0));
582  }
583  else
584  {
586  m_edca = nullptr;
587  }
588  m_initialFrame = false;
589 }
590 
591 void
593 {
594  NS_LOG_FUNCTION(this);
595 
596  // TODO This will be removed once no Txop is installed on a QoS station
597  if (!m_edca)
598  {
600  return;
601  }
602 
603  if (m_initialFrame)
604  {
605  // The backoff procedure shall be invoked by an EDCAF when the transmission
606  // of an MPDU in the initial PPDU of a TXOP fails (Sec. 10.22.2.2 of 802.11-2016)
607  NS_LOG_DEBUG("TX of the initial frame of a TXOP failed: terminate TXOP");
609  m_edca = nullptr;
610  }
611  else
612  {
614  "Cannot transmit more than one frame if TXOP Limit is zero");
615 
616  // A STA can perform a PIFS recovery or perform a backoff as a response to
617  // transmission failure within a TXOP. How it chooses between these two is
618  // implementation dependent. (Sec. 10.22.2.2 of 802.11-2016)
619  if (m_pifsRecovery)
620  {
621  // we can continue the TXOP if the carrier sense mechanism indicates that
622  // the medium is idle in a PIFS
623  NS_LOG_DEBUG("TX of a non-initial frame of a TXOP failed: perform PIFS recovery");
627  }
628  else
629  {
630  // In order not to terminate (yet) the TXOP, we call the NotifyChannelReleased
631  // method of the Txop class, which only generates a new backoff value and
632  // requests channel access if needed,
633  NS_LOG_DEBUG("TX of a non-initial frame of a TXOP failed: invoke backoff");
634  m_edca->Txop::NotifyChannelReleased(m_linkId);
636  m_edca = nullptr;
637  }
638  }
639  m_initialFrame = false;
640 }
641 
642 void
644 {
645  NS_LOG_FUNCTION(this << psdu << txVector);
646 
647  // APs store buffer size report of associated stations
648  if (m_mac->GetTypeOfStation() == AP && psdu->GetAddr1() == m_self)
649  {
650  for (const auto& mpdu : *PeekPointer(psdu))
651  {
652  const WifiMacHeader& hdr = mpdu->GetHeader();
653 
654  if (hdr.IsQosData() && hdr.IsQosEosp())
655  {
656  NS_LOG_DEBUG("Station " << hdr.GetAddr2() << " reported a buffer status of "
657  << +hdr.GetQosQueueSize()
658  << " for tid=" << +hdr.GetQosTid());
659  StaticCast<ApWifiMac>(m_mac)->SetBufferStatus(
660  hdr.GetQosTid(),
661  mpdu->GetOriginal()->GetHeader().GetAddr2(),
662  hdr.GetQosQueueSize());
663  }
664  }
665  }
666 
667  // before updating the NAV, check if the NAV counted down to zero. In such a
668  // case, clear the saved TXOP holder address.
670 
672 }
673 
674 void
676 {
677  NS_LOG_FUNCTION(this << psdu << txVector);
678 
679  SetTxopHolder(psdu, txVector);
681 }
682 
683 void
685 {
686  NS_LOG_FUNCTION(this << psdu << txVector);
687 
688  const WifiMacHeader& hdr = psdu->GetHeader(0);
689 
690  // A STA shall save the TXOP holder address for the BSS in which it is associated.
691  // The TXOP holder address is the MAC address from the Address 2 field of the frame
692  // that initiated a frame exchange sequence, except if this is a CTS frame, in which
693  // case the TXOP holder address is the Address 1 field. (Sec. 10.23.2.4 of 802.11-2020)
694  if ((hdr.IsQosData() || hdr.IsMgt() || hdr.IsRts()) &&
695  (hdr.GetAddr1() == m_bssid || hdr.GetAddr2() == m_bssid))
696  {
697  m_txopHolder = psdu->GetAddr2();
698  }
699  else if (hdr.IsCts() && hdr.GetAddr1() == m_bssid)
700  {
701  m_txopHolder = psdu->GetAddr1();
702  }
703 }
704 
705 void
707 {
708  NS_LOG_FUNCTION(this);
709  if (m_navEnd <= Simulator::Now())
710  {
711  m_txopHolder.reset();
712  }
713 }
714 
715 void
717 {
718  NS_LOG_FUNCTION(this);
721 }
722 
723 void
725  RxSignalInfo rxSignalInfo,
726  const WifiTxVector& txVector,
727  bool inAmpdu)
728 {
729  // The received MPDU is either broadcast or addressed to this station
730  NS_ASSERT(mpdu->GetHeader().GetAddr1().IsGroup() || mpdu->GetHeader().GetAddr1() == m_self);
731 
732  double rxSnr = rxSignalInfo.snr;
733  const WifiMacHeader& hdr = mpdu->GetHeader();
734 
735  if (hdr.IsCfEnd())
736  {
737  // reset NAV
738  NavResetTimeout();
739  return;
740  }
741 
742  if (hdr.IsRts())
743  {
744  NS_ABORT_MSG_IF(inAmpdu, "Received RTS as part of an A-MPDU");
745 
746  // If a non-VHT STA receives an RTS frame with the RA address matching the
747  // MAC address of the STA and the MAC address in the TA field in the RTS
748  // frame matches the saved TXOP holder address, then the STA shall send the
749  // CTS frame after SIFS, without regard for, and without resetting, its NAV.
750  // (sec. 10.22.2.4 of 802.11-2016)
751  if (hdr.GetAddr2() == m_txopHolder || VirtualCsMediumIdle())
752  {
753  NS_LOG_DEBUG("Received RTS from=" << hdr.GetAddr2() << ", schedule CTS");
756  this,
757  hdr,
758  txVector.GetMode(),
759  rxSnr);
760  }
761  else
762  {
763  NS_LOG_DEBUG("Received RTS from=" << hdr.GetAddr2() << ", cannot schedule CTS");
764  }
765  return;
766  }
767 
768  if (hdr.IsQosData())
769  {
770  if (hdr.GetAddr1() == m_self && hdr.GetQosAckPolicy() == WifiMacHeader::NORMAL_ACK)
771  {
772  NS_LOG_DEBUG("Received " << hdr.GetTypeString() << " from=" << hdr.GetAddr2()
773  << ", schedule ACK");
776  this,
777  hdr,
778  txVector,
779  rxSnr);
780  }
781 
782  // Forward up the frame if it is not a QoS Null frame
783  if (hdr.HasData())
784  {
785  m_rxMiddle->Receive(mpdu, m_linkId);
786  }
787 
788  // the received data frame has been processed
789  return;
790  }
791 
792  return FrameExchangeManager::ReceiveMpdu(mpdu, rxSignalInfo, txVector, inAmpdu);
793 }
794 
795 } // namespace ns3
#define max(a, b)
Definition: 80211b.c:43
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Time GetAccessGrantStart(bool ignoreNav=false) const
Access will never be granted to the medium before the time returned by this method.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
FrameExchangeManager is a base class handling the basic frame exchange sequences for non-QoS stations...
uint8_t m_linkId
the ID of the link this object is associated with
Ptr< WifiMac > m_mac
the MAC layer on this station
void SendMpduWithProtection(Ptr< WifiMpdu > mpdu, WifiTxParameters &txParams)
Send an MPDU with the given TX parameters (with the specified protection).
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager() const
void UpdateTxDuration(Mac48Address receiver, WifiTxParameters &txParams) const
Update the TX duration field of the given TX parameters after that the PSDU addressed to the given re...
virtual void CalculateAcknowledgmentTime(WifiAcknowledgment *acknowledgment) const
Calculate the time required to acknowledge a frame according to the given acknowledgment method.
void SendNormalAck(const WifiMacHeader &hdr, const WifiTxVector &dataTxVector, double dataSnr)
Send Normal Ack.
Mac48Address m_self
the MAC address of this device
virtual void TransmissionFailed()
Take necessary actions upon a transmission failure.
uint16_t m_allowedWidth
the allowed width in MHz for the current transmission
WifiTxTimer m_txTimer
the timer set upon frame transmission
void SendCtsAfterRts(const WifiMacHeader &rtsHdr, WifiMode rtsTxMode, double rtsSnr)
Send CTS after receiving RTS.
virtual Time GetRtsDurationId(const WifiTxVector &rtsTxVector, Time txDuration, Time response) const
Compute how to set the Duration/ID field of an RTS frame to send to protect a frame transmitted with ...
virtual void ForwardMpduDown(Ptr< WifiMpdu > mpdu, WifiTxVector &txVector)
Forward an MPDU down to the PHY layer.
virtual bool VirtualCsMediumIdle() const
virtual void CalculateProtectionTime(WifiProtection *protection) const
Calculate the time required to protect a frame according to the given protection method.
Ptr< WifiAckManager > GetAckManager() const
Get the Acknowledgment Manager used by this node.
virtual void NavResetTimeout()
Reset the NAV upon expiration of the NAV reset timer.
Ptr< WifiProtectionManager > GetProtectionManager() const
Get the Protection Manager used by this node.
Ptr< MacRxMiddle > m_rxMiddle
the MAC RX Middle on this station
virtual void TransmissionSucceeded()
Take necessary actions upon a transmission success.
Ptr< Txop > m_dcf
the DCF/EDCAF that gained channel access
Ptr< WifiPhy > m_phy
the PHY layer on this station
Ptr< WifiMpdu > GetFirstFragmentIfNeeded(Ptr< WifiMpdu > mpdu)
Fragment the given MPDU if needed.
virtual void PreProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
Perform actions that are possibly needed when receiving any frame, independently of whether the frame...
virtual Time GetFrameDurationId(const WifiMacHeader &header, uint32_t size, const WifiTxParameters &txParams, Ptr< Packet > fragmentedPacket) const
Compute how to set the Duration/ID field of a frame being transmitted with the given TX parameters.
virtual Time GetCtsToSelfDurationId(const WifiTxVector &ctsTxVector, Time txDuration, Time response) const
Compute how to set the Duration/ID field of a CTS-to-self frame to send to protect a frame transmitte...
Mac48Address m_bssid
BSSID address (Mac48Address)
virtual void PostProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
Perform actions that are possibly needed after receiving any frame, independently of whether the fram...
Ptr< ChannelAccessManager > m_channelAccessManager
the channel access manager
virtual void ReceiveMpdu(Ptr< const WifiMpdu > mpdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, bool inAmpdu)
This method handles the reception of an MPDU (possibly included in an A-MPDU)
Time m_navEnd
NAV expiration time.
void DoDispose() override
Destructor implementation.
virtual bool StartTransmission(Ptr< Txop > dcf, uint16_t allowedWidth)
Request the FrameExchangeManager to start a frame exchange sequence.
virtual Time GetTxDuration(uint32_t ppduPayloadSize, Mac48Address receiver, const WifiTxParameters &txParams) const
Get the updated TX duration of the frame associated with the given TX parameters if the size of the P...
an EUI-48 address
Definition: mac48-address.h:46
static Mac48Address GetBroadcast()
QosFrameExchangeManager handles the frame exchange sequences for QoS stations.
EventId m_pifsRecoveryEvent
event associated with an attempt of PIFS recovery
void ForwardMpduDown(Ptr< WifiMpdu > mpdu, WifiTxVector &txVector) override
Forward an MPDU down to the PHY layer.
virtual void ClearTxopHolderIfNeeded()
Clear the TXOP holder if the NAV counted down to zero (includes the case of NAV reset).
void ReceiveMpdu(Ptr< const WifiMpdu > mpdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, bool inAmpdu) override
This method handles the reception of an MPDU (possibly included in an A-MPDU)
void TransmissionFailed() override
Take necessary actions upon a transmission failure.
virtual bool StartFrameExchange(Ptr< QosTxop > edca, Time availableTime, bool initialFrame)
Start a frame exchange (including protection frames and acknowledgment frames as needed) that fits wi...
virtual void SetTxopHolder(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
Set the TXOP holder, if needed, based on the received frame.
Time GetFrameDurationId(const WifiMacHeader &header, uint32_t size, const WifiTxParameters &txParams, Ptr< Packet > fragmentedPacket) const override
Compute how to set the Duration/ID field of a frame being transmitted with the given TX parameters.
Time GetCtsToSelfDurationId(const WifiTxVector &ctsTxVector, Time txDuration, Time response) const override
Compute how to set the Duration/ID field of a CTS-to-self frame to send to protect a frame transmitte...
Ptr< QosTxop > m_edca
the EDCAF that gained channel access
virtual bool IsWithinLimitsIfAddMpdu(Ptr< const WifiMpdu > mpdu, const WifiTxParameters &txParams, Time ppduDurationLimit) const
Check whether the given MPDU can be added to the frame being built (as described by the given TX para...
std::optional< Mac48Address > m_txopHolder
MAC address of the TXOP holder.
void PostProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) override
Perform actions that are possibly needed after receiving any frame, independently of whether the fram...
bool StartTransmission(Ptr< Txop > edca, uint16_t allowedWidth) override
Request the FrameExchangeManager to start a frame exchange sequence.
Time GetRtsDurationId(const WifiTxVector &rtsTxVector, Time txDuration, Time response) const override
Compute how to set the Duration/ID field of an RTS frame to send to protect a frame transmitted with ...
virtual bool SendCfEndIfNeeded()
Send a CF-End frame to indicate the completion of the TXOP, provided that the remaining duration is l...
bool m_initialFrame
true if transmitting the initial frame of a TXOP
virtual Ptr< WifiMpdu > CreateAliasIfNeeded(Ptr< WifiMpdu > mpdu) const
Create an alias of the given MPDU for transmission by this Frame Exchange Manager.
void TransmissionSucceeded() override
Take necessary actions upon a transmission success.
static TypeId GetTypeId()
Get the type ID.
bool m_pifsRecovery
true if performing a PIFS recovery after failure
Ptr< Txop > m_edcaBackingOff
channel access function that invoked backoff during TXOP
void PreProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) override
Perform actions that are possibly needed when receiving any frame, independently of whether the frame...
bool m_setQosQueueSize
whether to set the Queue Size subfield of the QoS Control field of QoS data frames
void PifsRecovery()
Perform a PIFS recovery as a response to transmission failure within a TXOP.
virtual bool IsWithinSizeAndTimeLimits(uint32_t ppduPayloadSize, Mac48Address receiver, const WifiTxParameters &txParams, Time ppduDurationLimit) const
Check whether the transmission time of the frame being built (as described by the given TX parameters...
void NavResetTimeout() override
Reset the NAV upon expiration of the NAV reset timer.
void CancelPifsRecovery()
Cancel the PIFS recovery event and have the EDCAF attempting PIFS recovery release the channel.
bool TryAddMpdu(Ptr< const WifiMpdu > mpdu, WifiTxParameters &txParams, Time availableTime) const
Recompute the protection and acknowledgment methods to use if the given MPDU is added to the frame be...
void DoDispose() override
Destructor implementation.
Ptr< WifiMpdu > PeekNextMpdu(uint8_t linkId, uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast(), Ptr< const WifiMpdu > mpdu=nullptr)
Peek the next frame to transmit on the given link to the given receiver and of the given TID from the...
Definition: qos-txop.cc:359
void NotifyChannelReleased(uint8_t linkId) override
Called by the FrameExchangeManager to notify the completion of the transmissions.
Definition: qos-txop.cc:576
virtual Time GetRemainingTxop(uint8_t linkId) const
Return the remaining duration in the current TXOP on the given link.
Definition: qos-txop.cc:591
uint8_t GetQosQueueSize(uint8_t tid, Mac48Address receiver) const
Get the value for the Queue Size subfield of the QoS Control field of a QoS data frame of the given T...
Definition: qos-txop.cc:154
Ptr< WifiMpdu > GetNextMpdu(uint8_t linkId, Ptr< WifiMpdu > peekedItem, WifiTxParameters &txParams, Time availableTime, bool initialFrame)
Prepare the frame to transmit on the given link starting from the MPDU that has been previously peeke...
Definition: qos-txop.cc:474
void NotifyChannelAccessed(uint8_t linkId, Time txopDuration) override
Called by the FrameExchangeManager to notify that channel access has been granted on the given link f...
Definition: qos-txop.cc:557
virtual bool IsTxopStarted(uint8_t linkId) const
Return true if a TXOP has started on the given link.
Definition: qos-txop.cc:568
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:417
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition: nstime.h:350
bool IsNegative() const
Exactly equivalent to t <= 0.
Definition: nstime.h:323
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:286
@ MS
millisecond
Definition: nstime.h:117
bool IsZero() const
Exactly equivalent to t == 0.
Definition: nstime.h:314
Time GetTxopLimit() const
Return the TXOP limit.
Definition: txop.cc:473
virtual void NotifyChannelReleased(uint8_t linkId)
Called by the FrameExchangeManager to notify the completion of the transmissions.
Definition: txop.cc:585
virtual bool IsQosTxop() const
Check for QoS TXOP.
Definition: txop.cc:646
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
bool IsCts() const
Return true if the header is a CTS header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
void SetNoMoreFragments()
Un-set the More Fragment bit in the Frame Control Field.
bool IsMgt() const
Return true if the Type is Management.
uint32_t GetSize() const
Return the size of the WifiMacHeader in octets.
bool IsCfEnd() const
Return true if the header is a CF-End header.
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
bool IsQosEosp() const
Return if the end of service period (EOSP) is set.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
void SetQosQueueSize(uint8_t size)
Set the Queue Size subfield in the QoS control field.
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
const char * GetTypeString() const
Return a string corresponds to the header type.
bool HasData() const
Return true if the header type is DATA and is not DATA_NULL.
QosAckPolicy GetQosAckPolicy() const
Return the QoS Ack policy in the QoS control field.
void SetDuration(Time duration)
Set the Duration/ID field with the given duration (Time object).
bool IsRts() const
Return true if the header is a RTS header.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
bool IsQosData() const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
void SetQosEosp()
Set the end of service period (EOSP) bit in the QoS control field.
uint8_t GetQosQueueSize() const
Get the Queue Size subfield in the QoS control field.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
void SetNoRetry()
Un-set the Retry bit in the Frame Control field.
TypeOfStation GetTypeOfStation() const
Return the type of station.
Definition: wifi-mac.cc:418
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:490
void Send(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
This function is a wrapper for the Send variant that accepts a WifiConstPsduMap as first argument.
Definition: wifi-phy.cc:1693
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:774
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1480
static uint32_t GetMaxPsduSize(WifiModulationClass modulation)
Get the maximum PSDU size in bytes for the given modulation class.
Definition: wifi-phy.cc:1509
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:996
Time GetPifs() const
Return the PCF Interframe Space (PIFS) for this PHY.
Definition: wifi-phy.cc:798
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition: wifi-psdu.cc:279
Mac48Address GetAddr2() const
Get the Transmitter Address (TA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:128
Mac48Address GetAddr1() const
Get the Receiver Address (RA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:113
WifiTxVector GetDataTxVector(const WifiMacHeader &header, uint16_t allowedWidth)
WifiTxVector GetRtsTxVector(Mac48Address address)
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
std::unique_ptr< WifiProtection > m_protection
protection method
std::unique_ptr< WifiAcknowledgment > m_acknowledgment
acknowledgment method
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
void AddMpdu(Ptr< const WifiMpdu > mpdu)
Record that an MPDU is being added to the current frame.
bool IsRunning() const
Return true if the timer is running.
void Cancel()
Cancel the timer.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
WifiPreamble GetPreambleType() const
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:848
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Time GetPpduMaxTime(WifiPreamble preamble)
Get the maximum PPDU duration (see Section 10.14 of 802.11-2016) for the PHY layers defining the aPPD...
@ STA
Definition: wifi-mac.h:62
@ AP
Definition: wifi-mac.h:63
static const uint16_t WIFI_MAC_FCS_LENGTH
The length in octets of the IEEE 802.11 MAC FCS field.
uint32_t GetRtsSize()
Return the total RTS size (including FCS trailer).
Definition: wifi-utils.cc:103
@ WIFI_MAC_CTL_END
uint32_t GetCtsSize()
Return the total CTS size (including FCS trailer).
Definition: wifi-utils.cc:111
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:488
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:70
double snr
SNR in linear scale.
Definition: phy-entity.h:71