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 
100  WifiTxVector cfEndTxVector =
101  GetWifiRemoteStationManager()->GetRtsTxVector(cfEnd.GetAddr1(), m_allowedWidth);
102 
103  auto mpdu = Create<WifiMpdu>(Create<Packet>(), cfEnd);
104  auto txDuration =
105  m_phy->CalculateTxDuration(mpdu->GetSize(), cfEndTxVector, m_phy->GetPhyBand());
106 
107  // Send the CF-End frame if the remaining duration is long enough to transmit this frame
108  if (m_edca->GetRemainingTxop(m_linkId) > txDuration)
109  {
110  NS_LOG_DEBUG("Send CF-End frame");
111  ForwardMpduDown(mpdu, cfEndTxVector);
112  Simulator::Schedule(txDuration,
114  this,
115  m_edca);
116  return true;
117  }
118 
120  m_edca = nullptr;
121  return false;
122 }
123 
124 void
126 {
127  NS_LOG_FUNCTION(this);
128  NS_ASSERT(m_edca);
129  NS_ASSERT(m_edca->GetTxopStartTime(m_linkId).has_value());
130 
131  // Release the channel if it has not been idle for the last PIFS interval
135 
136  if (m_allowedWidth == 0)
137  {
139  m_edca = nullptr;
140  }
141  else
142  {
143  // the txopDuration parameter is unused because we are not starting a new TXOP
145  }
146 }
147 
148 void
150 {
151  NS_LOG_FUNCTION(this);
153  NS_ASSERT(m_edca);
154 
155  NS_LOG_DEBUG("Cancel PIFS recovery being attempted by EDCAF " << m_edca);
158 }
159 
160 bool
162 {
163  NS_LOG_FUNCTION(this << edca << allowedWidth);
164 
166  {
167  // Another AC (having AIFS=1 or lower, if the user changed the default settings)
168  // gained channel access while performing PIFS recovery. Abort PIFS recovery
170  }
171 
172  // TODO This will become an assert once no Txop is installed on a QoS station
173  if (!edca->IsQosTxop())
174  {
175  m_edca = nullptr;
176  return FrameExchangeManager::StartTransmission(edca, allowedWidth);
177  }
178 
179  m_allowedWidth = allowedWidth;
180  auto qosTxop = StaticCast<QosTxop>(edca);
181  return StartTransmission(qosTxop, qosTxop->GetTxopLimit(m_linkId));
182 }
183 
184 bool
186 {
187  NS_LOG_FUNCTION(this << edca << txopDuration);
188 
190  {
191  // Another AC (having AIFS=1 or lower, if the user changed the default settings)
192  // gained channel access while performing PIFS recovery. Abort PIFS recovery
194  }
195 
196  if (m_txTimer.IsRunning())
197  {
198  m_txTimer.Cancel();
199  }
200  m_dcf = edca;
201  m_edca = edca;
202 
203  // We check if this EDCAF invoked the backoff procedure (without terminating
204  // the TXOP) because the transmission of a non-initial frame of a TXOP failed
205  bool backingOff = (m_edcaBackingOff == m_edca);
206 
207  if (backingOff)
208  {
213 
214  // clear the member variable
215  m_edcaBackingOff = nullptr;
216  }
217 
219  {
220  // TXOP limit is not null. We have to check if this EDCAF is starting a
221  // new TXOP. This includes the case when the transmission of a non-initial
222  // frame of a TXOP failed and backoff was invoked without terminating the
223  // TXOP. In such a case, we assume that a new TXOP is being started if it
224  // elapsed more than TXOPlimit since the start of the paused TXOP. Note
225  // that GetRemainingTxop returns 0 iff Now - TXOPstart >= TXOPlimit
227  (backingOff && m_edca->GetRemainingTxop(m_linkId).IsZero()))
228  {
229  // starting a new TXOP
230  m_edca->NotifyChannelAccessed(m_linkId, txopDuration);
231 
232  if (StartFrameExchange(m_edca, txopDuration, true))
233  {
234  m_initialFrame = true;
235  return true;
236  }
237 
238  // TXOP not even started, return false
239  NS_LOG_DEBUG("No frame transmitted");
241  m_edca = nullptr;
242  return false;
243  }
244 
245  // We are continuing a TXOP, check if we can transmit another frame
247 
249  {
250  NS_LOG_DEBUG("Not enough remaining TXOP time");
251  return SendCfEndIfNeeded();
252  }
253 
254  return true;
255  }
256 
257  // we get here if TXOP limit is null
258  m_initialFrame = true;
259 
260  if (StartFrameExchange(m_edca, Time::Min(), true))
261  {
263  return true;
264  }
265 
266  NS_LOG_DEBUG("No frame transmitted");
268  m_edca = nullptr;
269  return false;
270 }
271 
272 bool
274  Time availableTime,
275  bool initialFrame)
276 {
277  NS_LOG_FUNCTION(this << edca << availableTime << initialFrame);
278 
279  Ptr<WifiMpdu> mpdu = edca->PeekNextMpdu(m_linkId);
280 
281  // Even though channel access is requested when the queue is not empty, at
282  // the time channel access is granted the lifetime of the packet might be
283  // expired and the queue might be empty.
284  if (!mpdu)
285  {
286  NS_LOG_DEBUG("Queue empty");
287  return false;
288  }
289 
290  mpdu = CreateAliasIfNeeded(mpdu);
291  WifiTxParameters txParams;
292  txParams.m_txVector =
293  GetWifiRemoteStationManager()->GetDataTxVector(mpdu->GetHeader(), m_allowedWidth);
294 
295  Ptr<WifiMpdu> item = edca->GetNextMpdu(m_linkId, mpdu, txParams, availableTime, initialFrame);
296 
297  if (!item)
298  {
299  NS_LOG_DEBUG("Not enough time to transmit a frame");
300  return false;
301  }
302 
303  NS_ASSERT_MSG(!item->GetHeader().IsQosData() || !item->GetHeader().IsQosAmsdu(),
304  "We should not get an A-MSDU here");
305 
306  // check if the MSDU needs to be fragmented
307  item = GetFirstFragmentIfNeeded(item);
308 
309  // update the protection method if the frame was fragmented
310  if (item->IsFragment() && item->GetSize() != mpdu->GetSize())
311  {
312  WifiTxParameters fragmentTxParams;
313  fragmentTxParams.m_txVector = txParams.m_txVector;
314  txParams.m_protection = GetProtectionManager()->TryAddMpdu(item, fragmentTxParams);
315  NS_ASSERT(txParams.m_protection);
316  }
317 
318  SendMpduWithProtection(item, txParams);
319 
320  return true;
321 }
322 
325 {
326  return mpdu;
327 }
328 
329 bool
331  WifiTxParameters& txParams,
332  Time availableTime) const
333 {
334  NS_ASSERT(mpdu);
335  NS_LOG_FUNCTION(this << *mpdu << &txParams << availableTime);
336 
337  // check if adding the given MPDU requires a different protection method
338  Time protectionTime = Time::Min(); // uninitialized
339  if (txParams.m_protection)
340  {
341  protectionTime = txParams.m_protection->protectionTime;
342  }
343 
344  std::unique_ptr<WifiProtection> protection;
345  protection = GetProtectionManager()->TryAddMpdu(mpdu, txParams);
346  bool protectionSwapped = false;
347 
348  if (protection)
349  {
350  // the protection method has changed, calculate the new protection time
351  CalculateProtectionTime(protection.get());
352  protectionTime = protection->protectionTime;
353  // swap unique pointers, so that the txParams that is passed to the next
354  // call to IsWithinLimitsIfAddMpdu is the most updated one
355  txParams.m_protection.swap(protection);
356  protectionSwapped = true;
357  }
358  NS_ASSERT(protectionTime != Time::Min());
359  NS_LOG_DEBUG("protection time=" << protectionTime);
360 
361  // check if adding the given MPDU requires a different acknowledgment method
362  Time acknowledgmentTime = Time::Min(); // uninitialized
363  if (txParams.m_acknowledgment)
364  {
365  acknowledgmentTime = txParams.m_acknowledgment->acknowledgmentTime;
366  }
367 
368  std::unique_ptr<WifiAcknowledgment> acknowledgment;
369  acknowledgment = GetAckManager()->TryAddMpdu(mpdu, txParams);
370  bool acknowledgmentSwapped = false;
371 
372  if (acknowledgment)
373  {
374  // the acknowledgment method has changed, calculate the new acknowledgment time
375  CalculateAcknowledgmentTime(acknowledgment.get());
376  acknowledgmentTime = acknowledgment->acknowledgmentTime;
377  // swap unique pointers, so that the txParams that is passed to the next
378  // call to IsWithinLimitsIfAddMpdu is the most updated one
379  txParams.m_acknowledgment.swap(acknowledgment);
380  acknowledgmentSwapped = true;
381  }
382  NS_ASSERT(acknowledgmentTime != Time::Min());
383  NS_LOG_DEBUG("acknowledgment time=" << acknowledgmentTime);
384 
385  Time ppduDurationLimit = Time::Min();
386  if (availableTime != Time::Min())
387  {
388  ppduDurationLimit = availableTime - protectionTime - acknowledgmentTime;
389  }
390 
391  if (!IsWithinLimitsIfAddMpdu(mpdu, txParams, ppduDurationLimit))
392  {
393  // adding MPDU failed, restore protection and acknowledgment methods
394  // if they were swapped
395  if (protectionSwapped)
396  {
397  txParams.m_protection.swap(protection);
398  }
399  if (acknowledgmentSwapped)
400  {
401  txParams.m_acknowledgment.swap(acknowledgment);
402  }
403  return false;
404  }
405 
406  // the given MPDU can be added, hence update the txParams
407  txParams.AddMpdu(mpdu);
408  UpdateTxDuration(mpdu->GetHeader().GetAddr1(), txParams);
409 
410  return true;
411 }
412 
413 bool
415  const WifiTxParameters& txParams,
416  Time ppduDurationLimit) const
417 {
418  NS_ASSERT(mpdu);
419  NS_LOG_FUNCTION(this << *mpdu << &txParams << ppduDurationLimit);
420 
421  // A QoS station only has to check that the MPDU transmission time does not
422  // exceed the given limit
423  return IsWithinSizeAndTimeLimits(mpdu->GetSize(),
424  mpdu->GetHeader().GetAddr1(),
425  txParams,
426  ppduDurationLimit);
427 }
428 
429 bool
431  Mac48Address receiver,
432  const WifiTxParameters& txParams,
433  Time ppduDurationLimit) const
434 {
435  NS_LOG_FUNCTION(this << ppduPayloadSize << receiver << &txParams << ppduDurationLimit);
436 
437  if (ppduDurationLimit != Time::Min() && ppduDurationLimit.IsNegative())
438  {
439  NS_LOG_DEBUG("ppduDurationLimit is null or negative, time limit is trivially exceeded");
440  return false;
441  }
442 
443  if (ppduPayloadSize > WifiPhy::GetMaxPsduSize(txParams.m_txVector.GetModulationClass()))
444  {
445  NS_LOG_DEBUG("the frame exceeds the max PSDU size");
446  return false;
447  }
448 
449  // Get the maximum PPDU Duration based on the preamble type
450  Time maxPpduDuration = GetPpduMaxTime(txParams.m_txVector.GetPreambleType());
451 
452  Time txTime = GetTxDuration(ppduPayloadSize, receiver, txParams);
453  NS_LOG_DEBUG("PPDU duration: " << txTime.As(Time::MS));
454 
455  if ((ppduDurationLimit.IsStrictlyPositive() && txTime > ppduDurationLimit) ||
456  (maxPpduDuration.IsStrictlyPositive() && txTime > maxPpduDuration))
457  {
458  NS_LOG_DEBUG(
459  "the frame does not meet the constraint on max PPDU duration or PPDU duration limit");
460  return false;
461  }
462 
463  return true;
464 }
465 
466 Time
468  uint32_t size,
469  const WifiTxParameters& txParams,
470  Ptr<Packet> fragmentedPacket) const
471 {
472  NS_LOG_FUNCTION(this << header << size << &txParams << fragmentedPacket);
473 
474  // TODO This will be removed once no Txop is installed on a QoS station
475  if (!m_edca)
476  {
477  return FrameExchangeManager::GetFrameDurationId(header, size, txParams, fragmentedPacket);
478  }
479 
481  {
482  return FrameExchangeManager::GetFrameDurationId(header, size, txParams, fragmentedPacket);
483  }
484 
485  NS_ASSERT(txParams.m_acknowledgment &&
486  txParams.m_acknowledgment->acknowledgmentTime != Time::Min());
487 
488  // under multiple protection settings, if the TXOP limit is not null, Duration/ID
489  // is set to cover the remaining TXOP time (Sec. 9.2.5.2 of 802.11-2016).
490  // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8
491  // of 802.11-2016)
493  m_phy->CalculateTxDuration(size, txParams.m_txVector, m_phy->GetPhyBand()),
494  txParams.m_acknowledgment->acknowledgmentTime);
495 }
496 
497 Time
499  Time txDuration,
500  Time response) const
501 {
502  NS_LOG_FUNCTION(this << rtsTxVector << txDuration << response);
503 
504  // TODO This will be removed once no Txop is installed on a QoS station
505  if (!m_edca)
506  {
507  return FrameExchangeManager::GetRtsDurationId(rtsTxVector, txDuration, response);
508  }
509 
511  {
512  return FrameExchangeManager::GetRtsDurationId(rtsTxVector, txDuration, response);
513  }
514 
515  // under multiple protection settings, if the TXOP limit is not null, Duration/ID
516  // is set to cover the remaining TXOP time (Sec. 9.2.5.2 of 802.11-2016).
517  // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8
518  // of 802.11-2016)
520  m_phy->CalculateTxDuration(GetRtsSize(), rtsTxVector, m_phy->GetPhyBand()),
521  Seconds(0));
522 }
523 
524 Time
526  Time txDuration,
527  Time response) const
528 {
529  NS_LOG_FUNCTION(this << ctsTxVector << txDuration << response);
530 
531  // TODO This will be removed once no Txop is installed on a QoS station
532  if (!m_edca)
533  {
534  return FrameExchangeManager::GetCtsToSelfDurationId(ctsTxVector, txDuration, response);
535  }
536 
538  {
539  return FrameExchangeManager::GetCtsToSelfDurationId(ctsTxVector, txDuration, response);
540  }
541 
542  // under multiple protection settings, if the TXOP limit is not null, Duration/ID
543  // is set to cover the remaining TXOP time (Sec. 9.2.5.2 of 802.11-2016).
544  // The TXOP holder may exceed the TXOP limit in some situations (Sec. 10.22.2.8
545  // of 802.11-2016)
547  m_phy->CalculateTxDuration(GetCtsSize(), ctsTxVector, m_phy->GetPhyBand()),
548  Seconds(0));
549 }
550 
551 void
553 {
554  NS_LOG_FUNCTION(this << *mpdu << txVector);
555 
556  WifiMacHeader& hdr = mpdu->GetHeader();
557 
558  if (hdr.IsQosData() && m_mac->GetTypeOfStation() == STA &&
559  (m_setQosQueueSize || hdr.IsQosEosp()))
560  {
561  uint8_t tid = hdr.GetQosTid();
562  hdr.SetQosEosp();
563  hdr.SetQosQueueSize(m_mac->GetQosTxop(tid)->GetQosQueueSize(tid, hdr.GetAddr1()));
564  }
566 }
567 
568 void
570 {
571  NS_LOG_DEBUG(this);
572 
573  // TODO This will be removed once no Txop is installed on a QoS station
574  if (!m_edca)
575  {
577  return;
578  }
579 
582  {
583  NS_LOG_DEBUG("Schedule another transmission in a SIFS");
586 
587  // we are continuing a TXOP, hence the txopDuration parameter is unused
588  Simulator::Schedule(m_phy->GetSifs(), fp, this, m_edca, Seconds(0));
589  }
590  else
591  {
593  m_edca = nullptr;
594  }
595  m_initialFrame = false;
596 }
597 
598 void
600 {
601  NS_LOG_FUNCTION(this);
602 
603  // TODO This will be removed once no Txop is installed on a QoS station
604  if (!m_edca)
605  {
607  return;
608  }
609 
610  if (m_initialFrame)
611  {
612  // The backoff procedure shall be invoked by an EDCAF when the transmission
613  // of an MPDU in the initial PPDU of a TXOP fails (Sec. 10.22.2.2 of 802.11-2016)
614  NS_LOG_DEBUG("TX of the initial frame of a TXOP failed: terminate TXOP");
616  m_edca = nullptr;
617  }
618  else
619  {
620  // some STA(s) did not respond, they are no longer protected
621  for (const auto& address : m_txTimer.GetStasExpectedToRespond())
622  {
623  NS_LOG_DEBUG(address << " did not respond, hence it is no longer protected");
624  m_protectedStas.erase(address);
625  }
626 
628  "Cannot transmit more than one frame if TXOP Limit is zero");
629 
630  // A STA can perform a PIFS recovery or perform a backoff as a response to
631  // transmission failure within a TXOP. How it chooses between these two is
632  // implementation dependent. (Sec. 10.22.2.2 of 802.11-2016)
633  if (m_pifsRecovery)
634  {
635  // we can continue the TXOP if the carrier sense mechanism indicates that
636  // the medium is idle in a PIFS
637  NS_LOG_DEBUG("TX of a non-initial frame of a TXOP failed: perform PIFS recovery");
641  }
642  else
643  {
644  // In order not to terminate (yet) the TXOP, we call the NotifyChannelReleased
645  // method of the Txop class, which only generates a new backoff value and
646  // requests channel access if needed,
647  NS_LOG_DEBUG("TX of a non-initial frame of a TXOP failed: invoke backoff");
648  m_edca->Txop::NotifyChannelReleased(m_linkId);
650  m_edca = nullptr;
651  }
652  }
653  m_initialFrame = false;
654 }
655 
656 void
658 {
659  NS_LOG_FUNCTION(this << psdu << txVector);
660 
661  // APs store buffer size report of associated stations
662  if (m_mac->GetTypeOfStation() == AP && psdu->GetAddr1() == m_self)
663  {
664  for (const auto& mpdu : *PeekPointer(psdu))
665  {
666  const WifiMacHeader& hdr = mpdu->GetHeader();
667 
668  if (hdr.IsQosData() && hdr.IsQosEosp())
669  {
670  NS_LOG_DEBUG("Station " << hdr.GetAddr2() << " reported a buffer status of "
671  << +hdr.GetQosQueueSize()
672  << " for tid=" << +hdr.GetQosTid());
673  StaticCast<ApWifiMac>(m_mac)->SetBufferStatus(
674  hdr.GetQosTid(),
675  mpdu->GetOriginal()->GetHeader().GetAddr2(),
676  hdr.GetQosQueueSize());
677  }
678  }
679  }
680 
681  // before updating the NAV, check if the NAV counted down to zero. In such a
682  // case, clear the saved TXOP holder address.
684 
686 }
687 
688 void
690 {
691  NS_LOG_FUNCTION(this << psdu << txVector);
692 
693  SetTxopHolder(psdu, txVector);
695 }
696 
697 void
699 {
700  NS_LOG_FUNCTION(this << psdu << txVector);
701 
702  const WifiMacHeader& hdr = psdu->GetHeader(0);
703 
704  // A STA shall save the TXOP holder address for the BSS in which it is associated.
705  // The TXOP holder address is the MAC address from the Address 2 field of the frame
706  // that initiated a frame exchange sequence, except if this is a CTS frame, in which
707  // case the TXOP holder address is the Address 1 field. (Sec. 10.23.2.4 of 802.11-2020)
708  if ((hdr.IsQosData() || hdr.IsMgt() || hdr.IsRts()) &&
709  (hdr.GetAddr1() == m_bssid || hdr.GetAddr2() == m_bssid))
710  {
711  m_txopHolder = psdu->GetAddr2();
712  }
713  else if (hdr.IsCts() && hdr.GetAddr1() == m_bssid)
714  {
715  m_txopHolder = psdu->GetAddr1();
716  }
717 }
718 
719 void
721 {
722  NS_LOG_FUNCTION(this);
723  if (m_navEnd <= Simulator::Now())
724  {
725  m_txopHolder.reset();
726  }
727 }
728 
729 void
731 {
732  NS_LOG_FUNCTION(this << psdu << txVector);
733  if (psdu->GetHeader(0).IsCfEnd())
734  {
735  NS_LOG_DEBUG("Received CF-End, resetting NAV");
736  NavResetTimeout();
737  return;
738  }
739 
740  FrameExchangeManager::UpdateNav(psdu, txVector);
741 }
742 
743 void
745 {
746  NS_LOG_FUNCTION(this);
749 }
750 
751 void
753  RxSignalInfo rxSignalInfo,
754  const WifiTxVector& txVector,
755  bool inAmpdu)
756 {
757  // The received MPDU is either broadcast or addressed to this station
758  NS_ASSERT(mpdu->GetHeader().GetAddr1().IsGroup() || mpdu->GetHeader().GetAddr1() == m_self);
759 
760  double rxSnr = rxSignalInfo.snr;
761  const WifiMacHeader& hdr = mpdu->GetHeader();
762 
763  if (hdr.IsRts())
764  {
765  NS_ABORT_MSG_IF(inAmpdu, "Received RTS as part of an A-MPDU");
766 
767  // If a non-VHT STA receives an RTS frame with the RA address matching the
768  // MAC address of the STA and the MAC address in the TA field in the RTS
769  // frame matches the saved TXOP holder address, then the STA shall send the
770  // CTS frame after SIFS, without regard for, and without resetting, its NAV.
771  // (sec. 10.22.2.4 of 802.11-2016)
772  if (hdr.GetAddr2() == m_txopHolder || VirtualCsMediumIdle())
773  {
774  NS_LOG_DEBUG("Received RTS from=" << hdr.GetAddr2() << ", schedule CTS");
777  this,
778  hdr,
779  txVector.GetMode(),
780  rxSnr);
781  }
782  else
783  {
784  NS_LOG_DEBUG("Received RTS from=" << hdr.GetAddr2() << ", cannot schedule CTS");
785  }
786  return;
787  }
788 
789  if (hdr.IsQosData())
790  {
791  if (hdr.GetAddr1() == m_self && hdr.GetQosAckPolicy() == WifiMacHeader::NORMAL_ACK)
792  {
793  NS_LOG_DEBUG("Received " << hdr.GetTypeString() << " from=" << hdr.GetAddr2()
794  << ", schedule ACK");
797  this,
798  hdr,
799  txVector,
800  rxSnr);
801  }
802 
803  // Forward up the frame
804  m_rxMiddle->Receive(mpdu, m_linkId);
805 
806  // the received data frame has been processed
807  return;
808  }
809 
810  return FrameExchangeManager::ReceiveMpdu(mpdu, rxSignalInfo, txVector, inAmpdu);
811 }
812 
813 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:41
#define max(a, b)
Definition: 80211b.c:42
uint16_t GetLargestIdlePrimaryChannel(Time interval, Time end)
Return the width of the largest primary channel that has been idle for the given time interval before...
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
virtual void UpdateNav(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
Update the NAV, if needed, based on the Duration/ID of the given psdu.
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.
std::set< Mac48Address > m_protectedStas
STAs that have replied to an RTS in this TXOP.
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 NotifyChannelReleased(Ptr< Txop > txop)
Notify the given Txop that channel has been released.
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.
void UpdateNav(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) override
Update the NAV, if needed, based on the Duration/ID of the given psdu.
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:378
virtual Time GetRemainingTxop(uint8_t linkId) const
Return the remaining duration in the current TXOP on the given link.
Definition: qos-txop.cc:636
virtual std::optional< Time > GetTxopStartTime(uint8_t linkId) const
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:179
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:495
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:580
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
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:415
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition: nstime.h:351
bool IsNegative() const
Exactly equivalent to t <= 0.
Definition: nstime.h:324
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:287
@ MS
millisecond
Definition: nstime.h:117
bool IsZero() const
Exactly equivalent to t == 0.
Definition: nstime.h:315
Time GetTxopLimit() const
Return the TXOP limit.
Definition: txop.cc:490
virtual bool IsQosTxop() const
Check for QoS TXOP.
Definition: txop.cc:687
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
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.
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.
virtual 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.
virtual const char * GetTypeString() const
Return a string corresponds to the header type.
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:422
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:499
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:781
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1507
static uint32_t GetMaxPsduSize(WifiModulationClass modulation)
Get the maximum PSDU size in bytes for the given modulation class.
Definition: wifi-phy.cc:1536
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1021
Time GetPifs() const
Return the PCF Interframe Space (PIFS) for this PHY.
Definition: wifi-phy.cc:805
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
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.
const std::set< Mac48Address > & GetStasExpectedToRespond() const
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
#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:1326
@ STA
Definition: wifi-mac.h:65
@ AP
Definition: wifi-mac.h:66
address
Definition: first.py:47
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:839
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...
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
uint32_t GetRtsSize()
Return the total RTS size (including FCS trailer).
Definition: wifi-utils.cc:103
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
@ 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:449
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:69
double snr
SNR in linear scale.
Definition: phy-entity.h:70