A Discrete-Event Network Simulator
API
phy-entity.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Orange Labs
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  * Authors: Rediet <getachew.redieteab@orange.com>
18  * Sébastien Deronne <sebastien.deronne@gmail.com> (for logic ported from wifi-phy and
19  * spectrum-wifi-phy) Mathieu Lacage <mathieu.lacage@sophia.inria.fr> (for logic ported from
20  * wifi-phy)
21  */
22 
23 #include "phy-entity.h"
24 
25 #include "frame-capture-model.h"
26 #include "interference-helper.h"
28 #include "spectrum-wifi-phy.h"
29 #include "wifi-psdu.h"
31 #include "wifi-utils.h"
32 
33 #include "ns3/assert.h"
34 #include "ns3/log.h"
35 #include "ns3/packet.h"
36 #include "ns3/simulator.h"
37 
38 #include <algorithm>
39 
40 namespace ns3
41 {
42 
43 NS_LOG_COMPONENT_DEFINE("PhyEntity");
44 
45 std::ostream&
46 operator<<(std::ostream& os, const PhyEntity::PhyRxFailureAction& action)
47 {
48  switch (action)
49  {
50  case PhyEntity::DROP:
51  return (os << "DROP");
52  case PhyEntity::ABORT:
53  return (os << "ABORT");
54  case PhyEntity::IGNORE:
55  return (os << "IGNORE");
56  default:
57  NS_FATAL_ERROR("Unknown action");
58  return (os << "unknown");
59  }
60 }
61 
62 std::ostream&
63 operator<<(std::ostream& os, const PhyEntity::PhyFieldRxStatus& status)
64 {
65  if (status.isSuccess)
66  {
67  return os << "success";
68  }
69  else
70  {
71  return os << "failure (" << status.reason << "/" << status.actionIfFailure << ")";
72  }
73 }
74 
75 /*******************************************************
76  * Abstract base class for PHY entities
77  *******************************************************/
78 
79 uint64_t PhyEntity::m_globalPpduUid = 0;
80 
82 {
83  NS_LOG_FUNCTION(this);
84  m_modeList.clear();
86 }
87 
88 void
90 {
91  NS_LOG_FUNCTION(this << wifiPhy);
92  m_wifiPhy = wifiPhy;
94 }
95 
96 bool
98 {
99  for (const auto& m : m_modeList)
100  {
101  if (m == mode)
102  {
103  return true;
104  }
105  }
106  return false;
107 }
108 
109 uint8_t
111 {
112  return m_modeList.size();
113 }
114 
115 WifiMode
116 PhyEntity::GetMcs(uint8_t /* index */) const
117 {
118  NS_ABORT_MSG(
119  "This method should be used only for HtPhy and child classes. Use GetMode instead.");
120  return WifiMode();
121 }
122 
123 bool
124 PhyEntity::IsMcsSupported(uint8_t /* index */) const
125 {
126  NS_ABORT_MSG("This method should be used only for HtPhy and child classes. Use IsModeSupported "
127  "instead.");
128  return false;
129 }
130 
131 bool
133 {
134  return false;
135 }
136 
137 std::list<WifiMode>::const_iterator
139 {
140  return m_modeList.begin();
141 }
142 
143 std::list<WifiMode>::const_iterator
145 {
146  return m_modeList.end();
147 }
148 
149 WifiMode
150 PhyEntity::GetSigMode(WifiPpduField field, const WifiTxVector& txVector) const
151 {
152  NS_FATAL_ERROR("PPDU field is not a SIG field (no sense in retrieving the signaled mode) or is "
153  "unsupported: "
154  << field);
155  return WifiMode(); // should be overloaded
156 }
157 
160 {
161  auto ppduFormats = GetPpduFormats();
162  const auto itPpdu = ppduFormats.find(preamble);
163  if (itPpdu != ppduFormats.end())
164  {
165  const auto itField = std::find(itPpdu->second.begin(), itPpdu->second.end(), currentField);
166  if (itField != itPpdu->second.end())
167  {
168  const auto itNextField = std::next(itField, 1);
169  if (itNextField != itPpdu->second.end())
170  {
171  return *(itNextField);
172  }
173  NS_FATAL_ERROR("No field after " << currentField << " for " << preamble
174  << " for the provided PPDU formats");
175  }
176  else
177  {
178  NS_FATAL_ERROR("Unsupported PPDU field " << currentField << " for " << preamble
179  << " for the provided PPDU formats");
180  }
181  }
182  else
183  {
184  NS_FATAL_ERROR("Unsupported preamble " << preamble << " for the provided PPDU formats");
185  }
186  return WifiPpduField::WIFI_PPDU_FIELD_PREAMBLE; // Silence compiler warning
187 }
188 
189 Time
190 PhyEntity::GetDuration(WifiPpduField field, const WifiTxVector& txVector) const
191 {
192  if (field > WIFI_PPDU_FIELD_EHT_SIG)
193  {
194  NS_FATAL_ERROR("Unsupported PPDU field");
195  }
196  return MicroSeconds(0); // should be overloaded
197 }
198 
199 Time
201 {
202  Time duration = MicroSeconds(0);
203  for (uint8_t field = WIFI_PPDU_FIELD_PREAMBLE; field < WIFI_PPDU_FIELD_DATA; ++field)
204  {
205  duration += GetDuration(static_cast<WifiPpduField>(field), txVector);
206  }
207  return duration;
208 }
209 
212 {
213  return WifiConstPsduMap({std::make_pair(SU_STA_ID, psdu)});
214 }
215 
218 {
219  return ppdu->GetPsdu();
220 }
221 
223 PhyEntity::GetPhyHeaderSections(const WifiTxVector& txVector, Time ppduStart) const
224 {
225  PhyHeaderSections map;
226  WifiPpduField field = WIFI_PPDU_FIELD_PREAMBLE; // preamble always present
227  Time start = ppduStart;
228 
229  while (field != WIFI_PPDU_FIELD_DATA)
230  {
231  Time duration = GetDuration(field, txVector);
232  map[field] =
233  std::make_pair(std::make_pair(start, start + duration), GetSigMode(field, txVector));
234  // Move to next field
235  start += duration;
236  field = GetNextField(field, txVector.GetPreambleType());
237  }
238  return map;
239 }
240 
242 PhyEntity::BuildPpdu(const WifiConstPsduMap& psdus, const WifiTxVector& txVector, Time ppduDuration)
243 {
244  NS_LOG_FUNCTION(this << psdus << txVector << ppduDuration);
245  NS_FATAL_ERROR("This method is unsupported for the base PhyEntity class. Use the overloaded "
246  "version in the amendment-specific subclasses instead!");
247  return Create<WifiPpdu>(psdus.begin()->second,
248  txVector,
250  txVector.GetChannelWidth())); // should be overloaded
251 }
252 
253 Time
255 {
256  if (field ==
257  WIFI_PPDU_FIELD_DATA) // this field is not in the map returned by GetPhyHeaderSections
258  {
259  return CalculatePhyPreambleAndHeaderDuration(txVector);
260  }
261  const auto& sections = GetPhyHeaderSections(txVector, NanoSeconds(0));
262  auto it = sections.find(field);
263  NS_ASSERT(it != sections.end());
264  const auto& startStopTimes = it->second.first;
265  return startStopTimes
266  .first; // return the start time of field relatively to the beginning of the PPDU
267 }
268 
271 {
272  uint16_t measurementChannelWidth = GetMeasurementChannelWidth(event->GetPpdu());
273  return m_wifiPhy->m_interference->CalculatePhyHeaderSnrPer(
274  event,
275  measurementChannelWidth,
276  GetPrimaryBand(measurementChannelWidth),
277  field);
278 }
279 
280 void
282 {
283  NS_LOG_FUNCTION(this << field << *event);
284  NS_ASSERT(m_wifiPhy); // no sense if no owner WifiPhy instance
287  "Use the StartReceivePreamble method for preamble reception");
288  // Handle special cases of data reception
289  if (field == WIFI_PPDU_FIELD_DATA)
290  {
291  StartReceivePayload(event);
292  return;
293  }
294 
295  bool supported = DoStartReceiveField(field, event);
296  NS_ABORT_MSG_IF(!supported,
297  "Unknown field "
298  << field << " for this PHY entity"); // TODO see what to do if not supported
299  Time duration = GetDuration(field, event->GetTxVector());
301  Simulator::Schedule(duration, &PhyEntity::EndReceiveField, this, field, event);
303  event->GetPpdu(),
304  duration); // keep in CCA busy state up to reception of Data (will then switch to RX)
305 }
306 
307 void
309 {
310  NS_LOG_FUNCTION(this << field << *event);
311  NS_ASSERT(m_wifiPhy); // no sense if no owner WifiPhy instance
313  PhyFieldRxStatus status = DoEndReceiveField(field, event);
314  WifiTxVector txVector = event->GetTxVector();
315  if (status.isSuccess) // move to next field if reception succeeded
316  {
317  StartReceiveField(GetNextField(field, txVector.GetPreambleType()), event);
318  }
319  else
320  {
321  Ptr<const WifiPpdu> ppdu = event->GetPpdu();
322  switch (status.actionIfFailure)
323  {
324  case ABORT:
325  // Abort reception, but consider medium as busy
327  if (event->GetEndTime() > (Simulator::Now() + m_state->GetDelayUntilIdle()))
328  {
330  }
331  break;
332  case DROP:
333  // Notify drop, keep in CCA busy, and perform same processing as IGNORE case
334  if (status.reason == FILTERED)
335  {
336  // PHY-RXSTART is immediately followed by PHY-RXEND (Filtered)
338  txVector,
339  NanoSeconds(0)); // this callback (equivalent to PHY-RXSTART primitive) is also
340  // triggered for filtered PPDUs
341  }
344  // no break
345  case IGNORE:
346  // Keep in Rx state and reset at end
347  m_endRxPayloadEvents.push_back(
350  this,
351  event));
352  break;
353  default:
354  NS_FATAL_ERROR("Unknown action in case of failure");
355  }
356  }
357 }
358 
359 Time
361 {
362  const WifiTxVector& txVector = ppdu->GetTxVector();
363  return ppdu->GetTxDuration() -
364  (GetDurationUpToField(field, txVector) + GetDuration(field, txVector));
365 }
366 
367 bool
369 {
370  NS_LOG_FUNCTION(this << field << *event);
372  field != WIFI_PPDU_FIELD_DATA); // handled apart for the time being
373  auto ppduFormats = GetPpduFormats();
374  auto itFormat = ppduFormats.find(event->GetPpdu()->GetPreamble());
375  if (itFormat != ppduFormats.end())
376  {
377  auto itField = std::find(itFormat->second.begin(), itFormat->second.end(), field);
378  if (itField != itFormat->second.end())
379  {
380  return true; // supported field so we can start receiving
381  }
382  }
383  return false; // unsupported otherwise
384 }
385 
388 {
389  NS_LOG_FUNCTION(this << field << *event);
390  NS_ASSERT(field != WIFI_PPDU_FIELD_DATA); // handled apart for the time being
391  if (field == WIFI_PPDU_FIELD_PREAMBLE)
392  {
393  return DoEndReceivePreamble(event);
394  }
395  return PhyFieldRxStatus(false); // failed reception by default
396 }
397 
398 void
400  RxPowerWattPerChannelBand& rxPowersW,
401  Time rxDuration)
402 {
403  // The total RX power corresponds to the maximum over all the bands
404  auto it = std::max_element(
405  rxPowersW.begin(),
406  rxPowersW.end(),
407  [](const std::pair<WifiSpectrumBand, double>& p1,
408  const std::pair<WifiSpectrumBand, double>& p2) { return p1.second < p2.second; });
409  NS_LOG_FUNCTION(this << ppdu << it->second);
410 
411  Ptr<Event> event = m_wifiPhy->GetPhyEntityForPpdu(ppdu)->DoGetEvent(
412  ppdu,
413  rxPowersW); // use latest PHY entity to handle MU-RTS sent with non-HT rate
414  if (!event)
415  {
416  // PPDU should be simply considered as interference (once it has been accounted for in
417  // InterferenceHelper)
418  return;
419  }
420 
421  Time endRx = Simulator::Now() + rxDuration;
422  if (m_state->GetState() == WifiPhyState::OFF)
423  {
424  NS_LOG_DEBUG("Cannot start RX because device is OFF");
425  if (endRx > (Simulator::Now() + m_state->GetDelayUntilIdle()))
426  {
428  }
430  return;
431  }
432 
433  if (ppdu->IsTruncatedTx())
434  {
435  NS_LOG_DEBUG("Packet reception stopped because transmitter has been switched off");
436  if (endRx > (Simulator::Now() + m_state->GetDelayUntilIdle()))
437  {
439  }
441  return;
442  }
443 
444  switch (m_state->GetState())
445  {
447  NS_LOG_DEBUG("Drop packet because of channel switching");
448  /*
449  * Packets received on the upcoming channel are added to the event list
450  * during the switching state. This way the medium can be correctly sensed
451  * when the device listens to the channel for the first time after the
452  * switching e.g. after channel switching, the channel may be sensed as
453  * busy due to other devices' transmissions started before the end of
454  * the switching.
455  */
456  DropPreambleEvent(ppdu, CHANNEL_SWITCHING, endRx);
457  break;
458  case WifiPhyState::RX:
460  m_wifiPhy->m_frameCaptureModel->IsInCaptureWindow(
462  m_wifiPhy->m_frameCaptureModel->CaptureNewFrame(m_wifiPhy->m_currentEvent, event))
463  {
465  NS_LOG_DEBUG("Switch to new packet");
467  }
468  else
469  {
470  NS_LOG_DEBUG("Drop packet because already in Rx");
471  DropPreambleEvent(ppdu, RXING, endRx);
473  {
474  /*
475  * We are here because the non-legacy PHY header has not been successfully received.
476  * The PHY is kept in RX state for the duration of the PPDU, but EndReceive function
477  * is not called when the reception of the PPDU is finished, which is responsible to
478  * clear m_currentPreambleEvents. As a result, m_currentPreambleEvents should be
479  * cleared here.
480  */
482  }
483  }
484  break;
485  case WifiPhyState::TX:
486  NS_LOG_DEBUG("Drop packet because already in Tx");
487  DropPreambleEvent(ppdu, TXING, endRx);
488  break;
491  {
493  m_wifiPhy->m_frameCaptureModel->IsInCaptureWindow(
495  m_wifiPhy->m_frameCaptureModel->CaptureNewFrame(m_wifiPhy->m_currentEvent, event))
496  {
498  NS_LOG_DEBUG("Switch to new packet");
500  }
501  else
502  {
503  NS_LOG_DEBUG("Drop packet because already decoding preamble");
505  }
506  }
507  else
508  {
510  }
511  break;
512  case WifiPhyState::IDLE:
515  break;
516  case WifiPhyState::SLEEP:
517  NS_LOG_DEBUG("Drop packet because in sleep mode");
518  DropPreambleEvent(ppdu, SLEEPING, endRx);
519  break;
520  default:
521  NS_FATAL_ERROR("Invalid WifiPhy state.");
522  break;
523  }
524 }
525 
526 void
528 {
529  NS_LOG_FUNCTION(this << ppdu << reason << endRx);
531  auto it = m_wifiPhy->m_currentPreambleEvents.find(
532  std::make_pair(ppdu->GetUid(), ppdu->GetPreamble()));
533  if (it != m_wifiPhy->m_currentPreambleEvents.end())
534  {
536  }
537  if (!m_wifiPhy->IsStateSleep() && !m_wifiPhy->IsStateOff() &&
538  (endRx > (Simulator::Now() + m_state->GetDelayUntilIdle())))
539  {
540  // that PPDU will be noise _after_ the end of the current event.
542  }
543 }
544 
545 void
547 {
548  NS_LOG_FUNCTION(this << ppdu << rxDuration);
549  auto it = m_wifiPhy->m_currentPreambleEvents.find(
550  std::make_pair(ppdu->GetUid(), ppdu->GetPreamble()));
551  if (it != m_wifiPhy->m_currentPreambleEvents.end())
552  {
554  }
555  if (m_wifiPhy->m_currentPreambleEvents.empty())
556  {
557  m_wifiPhy->Reset();
558  }
559 
560  if (rxDuration > m_state->GetDelayUntilIdle())
561  {
562  // this PPDU will be noise _after_ the completion of the current event
564  }
565 }
566 
567 uint16_t
569 {
570  return SU_STA_ID;
571 }
572 
573 void
575 {
576  NS_LOG_FUNCTION(this << *event);
578 
579  Time payloadDuration = DoStartReceivePayload(event);
580  m_state->SwitchToRx(payloadDuration);
581 }
582 
583 Time
585 {
586  NS_LOG_FUNCTION(this << *event);
587  Ptr<const WifiPpdu> ppdu = event->GetPpdu();
588  NS_LOG_DEBUG("Receiving PSDU");
589  uint16_t staId = GetStaId(ppdu);
590  m_signalNoiseMap.insert({std::make_pair(ppdu->GetUid(), staId), SignalNoiseDbm()});
591  m_statusPerMpduMap.insert({std::make_pair(ppdu->GetUid(), staId), std::vector<bool>()});
592  ScheduleEndOfMpdus(event);
593  const WifiTxVector& txVector = event->GetTxVector();
594  Time payloadDuration = ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector);
596  txVector,
597  payloadDuration); // this callback (equivalent to PHY-RXSTART primitive) is triggered only
598  // if headers have been correctly decoded and that the mode within is
599  // supported
600  m_endRxPayloadEvents.push_back(
601  Simulator::Schedule(payloadDuration, &PhyEntity::EndReceivePayload, this, event));
602  return payloadDuration;
603 }
604 
605 void
607 {
608  NS_LOG_FUNCTION(this << *event);
609  Ptr<const WifiPpdu> ppdu = event->GetPpdu();
611  const WifiTxVector& txVector = event->GetTxVector();
612  uint16_t staId = GetStaId(ppdu);
613  Time endOfMpduDuration = NanoSeconds(0);
614  Time relativeStart = NanoSeconds(0);
615  Time psduDuration = ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector);
616  Time remainingAmpduDuration = psduDuration;
617  size_t nMpdus = psdu->GetNMpdus();
618  MpduType mpduType =
619  (nMpdus > 1) ? FIRST_MPDU_IN_AGGREGATE : (psdu->IsSingle() ? SINGLE_MPDU : NORMAL_MPDU);
620  uint32_t totalAmpduSize = 0;
621  double totalAmpduNumSymbols = 0.0;
622  auto mpdu = psdu->begin();
623  for (size_t i = 0; i < nMpdus && mpdu != psdu->end(); ++mpdu)
624  {
625  uint32_t size = (mpduType == NORMAL_MPDU) ? psdu->GetSize() : psdu->GetAmpduSubframeSize(i);
626  Time mpduDuration = m_wifiPhy->GetPayloadDuration(size,
627  txVector,
629  mpduType,
630  true,
631  totalAmpduSize,
632  totalAmpduNumSymbols,
633  staId);
634 
635  remainingAmpduDuration -= mpduDuration;
636  if (i == (nMpdus - 1) && !remainingAmpduDuration.IsZero()) // no more MPDUs coming
637  {
638  if (remainingAmpduDuration <
639  NanoSeconds(txVector.GetGuardInterval())) // enables to ignore padding
640  {
641  mpduDuration += remainingAmpduDuration; // apply a correction just in case rounding
642  // had induced slight shift
643  }
644  }
645 
646  endOfMpduDuration += mpduDuration;
647  NS_LOG_INFO("Schedule end of MPDU #"
648  << i << " in " << endOfMpduDuration.As(Time::NS) << " (relativeStart="
649  << relativeStart.As(Time::NS) << ", mpduDuration=" << mpduDuration.As(Time::NS)
650  << ", remainingAmdpuDuration=" << remainingAmpduDuration.As(Time::NS) << ")");
651  m_endOfMpduEvents.push_back(Simulator::Schedule(endOfMpduDuration,
653  this,
654  event,
655  Create<WifiPsdu>(*mpdu, false),
656  i,
657  relativeStart,
658  mpduDuration));
659 
660  // Prepare next iteration
661  ++i;
662  relativeStart += mpduDuration;
663  mpduType = (i == (nMpdus - 1)) ? LAST_MPDU_IN_AGGREGATE : MIDDLE_MPDU_IN_AGGREGATE;
664  }
665 }
666 
667 void
669  Ptr<const WifiPsdu> psdu,
670  size_t mpduIndex,
671  Time relativeStart,
672  Time mpduDuration)
673 {
674  NS_LOG_FUNCTION(this << *event << mpduIndex << relativeStart << mpduDuration);
675  Ptr<const WifiPpdu> ppdu = event->GetPpdu();
676  WifiTxVector txVector = event->GetTxVector();
677  uint16_t staId = GetStaId(ppdu);
678 
679  std::pair<bool, SignalNoiseDbm> rxInfo =
680  GetReceptionStatus(psdu, event, staId, relativeStart, mpduDuration);
681  NS_LOG_DEBUG("Extracted MPDU #" << mpduIndex << ": duration: " << mpduDuration.As(Time::NS)
682  << ", correct reception: " << rxInfo.first << ", Signal/Noise: "
683  << rxInfo.second.signal << "/" << rxInfo.second.noise << "dBm");
684 
685  auto signalNoiseIt = m_signalNoiseMap.find(std::make_pair(ppdu->GetUid(), staId));
686  NS_ASSERT(signalNoiseIt != m_signalNoiseMap.end());
687  signalNoiseIt->second = rxInfo.second;
688 
689  RxSignalInfo rxSignalInfo;
690  rxSignalInfo.snr = rxInfo.second.signal / rxInfo.second.noise;
691  rxSignalInfo.rssi = rxInfo.second.signal;
692 
693  auto statusPerMpduIt = m_statusPerMpduMap.find(std::make_pair(ppdu->GetUid(), staId));
694  NS_ASSERT(statusPerMpduIt != m_statusPerMpduMap.end());
695  statusPerMpduIt->second.push_back(rxInfo.first);
696 
697  if (rxInfo.first && GetAddressedPsduInPpdu(ppdu)->GetNMpdus() > 1)
698  {
699  // only done for correct MPDU that is part of an A-MPDU
700  m_state->NotifyRxMpdu(psdu, rxSignalInfo, txVector);
701  }
702 }
703 
704 void
706 {
707  Ptr<const WifiPpdu> ppdu = event->GetPpdu();
708  WifiTxVector txVector = event->GetTxVector();
709  Time psduDuration = ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector);
710  NS_LOG_FUNCTION(this << *event << psduDuration);
711  NS_ASSERT(event->GetEndTime() == Simulator::Now());
712  uint16_t staId = GetStaId(ppdu);
713  const auto& channelWidthAndBand = GetChannelWidthAndBand(event->GetTxVector(), staId);
714  double snr = m_wifiPhy->m_interference->CalculateSnr(event,
715  channelWidthAndBand.first,
716  txVector.GetNss(staId),
717  channelWidthAndBand.second);
718 
720  m_wifiPhy->NotifyRxEnd(psdu);
721 
722  auto signalNoiseIt = m_signalNoiseMap.find(std::make_pair(ppdu->GetUid(), staId));
723  NS_ASSERT(signalNoiseIt != m_signalNoiseMap.end());
724  auto statusPerMpduIt = m_statusPerMpduMap.find(std::make_pair(ppdu->GetUid(), staId));
725  NS_ASSERT(statusPerMpduIt != m_statusPerMpduMap.end());
726 
727  if (std::count(statusPerMpduIt->second.begin(), statusPerMpduIt->second.end(), true))
728  {
729  // At least one MPDU has been successfully received
732  txVector,
733  signalNoiseIt->second,
734  statusPerMpduIt->second,
735  staId);
736  RxSignalInfo rxSignalInfo;
737  rxSignalInfo.snr = snr;
738  rxSignalInfo.rssi = signalNoiseIt->second.signal; // same information for all MPDUs
739  RxPayloadSucceeded(psdu, rxSignalInfo, txVector, staId, statusPerMpduIt->second);
741  ppdu->GetUid(); // store UID only if reception is successful (because otherwise trigger
742  // won't be read by MAC layer)
743  }
744  else
745  {
746  RxPayloadFailed(psdu, snr, txVector);
747  }
748 
749  DoEndReceivePayload(ppdu);
751 }
752 
753 void
755  RxSignalInfo rxSignalInfo,
756  const WifiTxVector& txVector,
757  uint16_t staId,
758  const std::vector<bool>& statusPerMpdu)
759 {
760  NS_LOG_FUNCTION(this << *psdu << txVector);
761  m_state->NotifyRxPsduSucceeded(psdu, rxSignalInfo, txVector, staId, statusPerMpdu);
762  m_state->SwitchFromRxEndOk();
763 }
764 
765 void
767 {
768  NS_LOG_FUNCTION(this << *psdu << txVector << snr);
769  m_state->NotifyRxPsduFailed(psdu, snr);
770  m_state->SwitchFromRxEndError();
771 }
772 
773 void
775 {
776  NS_LOG_FUNCTION(this << ppdu);
778  NotifyInterferenceRxEndAndClear(false); // don't reset WifiPhy
779 
780  m_wifiPhy->m_currentEvent = nullptr;
782  m_endRxPayloadEvents.clear();
783 }
784 
785 std::pair<bool, SignalNoiseDbm>
787  Ptr<Event> event,
788  uint16_t staId,
789  Time relativeMpduStart,
790  Time mpduDuration)
791 {
792  NS_LOG_FUNCTION(this << *psdu << *event << staId << relativeMpduStart << mpduDuration);
793  const auto& channelWidthAndBand = GetChannelWidthAndBand(event->GetTxVector(), staId);
794  SnrPer snrPer = m_wifiPhy->m_interference->CalculatePayloadSnrPer(
795  event,
796  channelWidthAndBand.first,
797  channelWidthAndBand.second,
798  staId,
799  std::make_pair(relativeMpduStart, relativeMpduStart + mpduDuration));
800 
801  WifiMode mode = event->GetTxVector().GetMode(staId);
802  NS_LOG_DEBUG("rate=" << (mode.GetDataRate(event->GetTxVector(), staId))
803  << ", SNR(dB)=" << RatioToDb(snrPer.snr) << ", PER=" << snrPer.per
804  << ", size=" << psdu->GetSize()
805  << ", relativeStart = " << relativeMpduStart.As(Time::NS)
806  << ", duration = " << mpduDuration.As(Time::NS));
807 
808  // There are two error checks: PER and receive error model check.
809  // PER check models is typical for Wi-Fi and is based on signal modulation;
810  // Receive error model is optional, if we have an error model and
811  // it indicates that the packet is corrupt, drop the packet.
812  SignalNoiseDbm signalNoise;
813  signalNoise.signal = WToDbm(event->GetRxPowerW(channelWidthAndBand.second));
814  signalNoise.noise = WToDbm(event->GetRxPowerW(channelWidthAndBand.second) / snrPer.snr);
815  if (GetRandomValue() > snrPer.per &&
817  m_wifiPhy->m_postReceptionErrorModel->IsCorrupt(psdu->GetPacket()->Copy())))
818  {
819  NS_LOG_DEBUG("Reception succeeded: " << psdu);
820  return std::make_pair(true, signalNoise);
821  }
822  else
823  {
824  NS_LOG_DEBUG("Reception failed: " << psdu);
825  return std::make_pair(false, signalNoise);
826  }
827 }
828 
829 std::pair<uint16_t, WifiSpectrumBand>
830 PhyEntity::GetChannelWidthAndBand(const WifiTxVector& txVector, uint16_t /* staId */) const
831 {
832  uint16_t channelWidth = GetRxChannelWidth(txVector);
833  return std::make_pair(channelWidth, GetPrimaryBand(channelWidth));
834 }
835 
836 const std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
838 {
840 }
841 
842 void
844 {
845  NS_LOG_FUNCTION(this << *event);
846  Ptr<const WifiPpdu> ppdu = event->GetPpdu();
848  {std::make_pair(ppdu->GetUid(), ppdu->GetPreamble()), event});
849 }
850 
853 {
854  Ptr<Event> event =
855  CreateInterferenceEvent(ppdu, ppdu->GetTxVector(), ppdu->GetTxDuration(), rxPowersW);
856 
857  // We store all incoming preamble events, and a decision is made at the end of the preamble
858  // detection window.
859  auto uidPreamblePair = std::make_pair(ppdu->GetUid(), ppdu->GetPreamble());
860  NS_ASSERT(m_wifiPhy->m_currentPreambleEvents.find(uidPreamblePair) ==
862  m_wifiPhy->m_currentPreambleEvents.insert({uidPreamblePair, event});
863  return event;
864 }
865 
868  const WifiTxVector& txVector,
869  Time duration,
870  RxPowerWattPerChannelBand& rxPower,
871  bool isStartOfdmaRxing /* = false */)
872 {
873  return m_wifiPhy->m_interference->Add(ppdu, txVector, duration, rxPower, isStartOfdmaRxing);
874 }
875 
876 void
878 {
879  m_wifiPhy->m_interference->UpdateEvent(event, rxPower);
880 }
881 
882 void
884 {
885  m_wifiPhy->m_interference->NotifyRxEnd(Simulator::Now());
886  m_signalNoiseMap.clear();
887  m_statusPerMpduMap.clear();
888  for (const auto& endOfMpduEvent : m_endOfMpduEvents)
889  {
890  NS_ASSERT(endOfMpduEvent.IsExpired());
891  }
892  m_endOfMpduEvents.clear();
893  if (reset)
894  {
895  m_wifiPhy->Reset();
896  }
897 }
898 
901 {
902  NS_LOG_FUNCTION(this << *event);
904  1); // Synched on one after detection period
905  return PhyFieldRxStatus(true); // always consider that preamble has been correctly received if
906  // preamble detection was OK
907 }
908 
909 void
911 {
912  NS_LOG_FUNCTION(this << *event);
913  NS_LOG_DEBUG("Sync to signal (power=" << WToDbm(GetRxPowerWForPpdu(event)) << "dBm)");
915  ->NotifyRxStart(); // We need to notify it now so that it starts recording events
919  this,
920  event));
921 }
922 
923 void
925 {
926  NS_LOG_FUNCTION(this << *event);
928  NS_ASSERT(m_wifiPhy->m_endPhyRxEvent.IsExpired()); // since end of preamble reception is
929  // scheduled by this method upon success
930 
931  // calculate PER on the measurement channel for PHY headers
932  uint16_t measurementChannelWidth = GetMeasurementChannelWidth(event->GetPpdu());
933  auto measurementBand = GetPrimaryBand(measurementChannelWidth);
934  double maxRxPowerW = -1; // in case current event may not be sent on measurement channel
935  // (rxPowerW would be equal to 0)
936  Ptr<Event> maxEvent;
938  for (auto preambleEvent : m_wifiPhy->m_currentPreambleEvents)
939  {
940  double rxPowerW = preambleEvent.second->GetRxPowerW(measurementBand);
941  if (rxPowerW > maxRxPowerW)
942  {
943  maxRxPowerW = rxPowerW;
944  maxEvent = preambleEvent.second;
945  }
946  }
947 
948  NS_ASSERT(maxEvent);
949  if (maxEvent != event)
950  {
951  NS_LOG_DEBUG("Receiver got a stronger packet with UID "
952  << maxEvent->GetPpdu()->GetUid()
953  << " during preamble detection: drop packet with UID "
954  << event->GetPpdu()->GetUid());
956  auto it = m_wifiPhy->m_currentPreambleEvents.find(
957  std::make_pair(event->GetPpdu()->GetUid(), event->GetPpdu()->GetPreamble()));
959  // This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to
960  // the power at the start of the PPDU
961  m_wifiPhy->m_interference->NotifyRxEnd(maxEvent->GetStartTime());
962  // Make sure InterferenceHelper keeps recording events
963  m_wifiPhy->m_interference->NotifyRxStart();
964  return;
965  }
966 
967  m_wifiPhy->m_currentEvent = event;
968 
969  double snr = m_wifiPhy->m_interference->CalculateSnr(m_wifiPhy->m_currentEvent,
970  measurementChannelWidth,
971  1,
972  measurementBand);
973  NS_LOG_DEBUG("SNR(dB)=" << RatioToDb(snr) << " at end of preamble detection period");
974 
975  if ((!m_wifiPhy->m_preambleDetectionModel && maxRxPowerW > 0.0) ||
977  m_wifiPhy->m_preambleDetectionModel->IsPreambleDetected(
978  m_wifiPhy->m_currentEvent->GetRxPowerW(measurementBand),
979  snr,
980  measurementChannelWidth)))
981  {
982  // A bit convoluted but it enables to sync all PHYs
983  for (auto& it : m_wifiPhy->m_phyEntities)
984  {
985  it.second->CancelRunningEndPreambleDetectionEvents(true);
986  }
987 
988  for (auto it = m_wifiPhy->m_currentPreambleEvents.begin();
989  it != m_wifiPhy->m_currentPreambleEvents.end();)
990  {
991  if (it->second != m_wifiPhy->m_currentEvent)
992  {
993  NS_LOG_DEBUG("Drop packet with UID " << it->first.first << " and preamble "
994  << it->first.second << " arrived at time "
995  << it->second->GetStartTime());
996  WifiPhyRxfailureReason reason;
997  if (m_wifiPhy->m_currentEvent->GetPpdu()->GetUid() > it->first.first)
998  {
1000  // This is needed to cleanup the m_firstPowerPerBand so that the first power
1001  // corresponds to the power at the start of the PPDU
1002  m_wifiPhy->m_interference->NotifyRxEnd(
1003  m_wifiPhy->m_currentEvent->GetStartTime());
1004  }
1005  else
1006  {
1007  reason = BUSY_DECODING_PREAMBLE;
1008  }
1009  m_wifiPhy->NotifyRxDrop(GetAddressedPsduInPpdu(it->second->GetPpdu()), reason);
1010  it = m_wifiPhy->m_currentPreambleEvents.erase(it);
1011  }
1012  else
1013  {
1014  ++it;
1015  }
1016  }
1017 
1018  // Make sure InterferenceHelper keeps recording events
1019  m_wifiPhy->m_interference->NotifyRxStart();
1020 
1022  m_wifiPhy->m_currentEvent->GetRxPowerWPerBand());
1024 
1025  // Continue receiving preamble
1026  Time durationTillEnd = GetDuration(WIFI_PPDU_FIELD_PREAMBLE, event->GetTxVector()) -
1028  m_wifiPhy->NotifyCcaBusy(event->GetPpdu(),
1029  durationTillEnd); // will be prolonged by next field
1030  m_wifiPhy->m_endPhyRxEvent = Simulator::Schedule(durationTillEnd,
1032  this,
1034  event);
1035  }
1036  else
1037  {
1038  NS_LOG_DEBUG("Drop packet because PHY preamble detection failed");
1039  // Like CCA-SD, CCA-ED is governed by the 4 us CCA window to flag CCA-BUSY
1040  // for any received signal greater than the CCA-ED threshold.
1043  m_wifiPhy->m_currentEvent->GetEndTime());
1044  if (m_wifiPhy->m_currentPreambleEvents.empty())
1045  {
1046  // Do not erase events if there are still pending preamble events to be processed
1047  m_wifiPhy->m_interference->NotifyRxEnd(Simulator::Now());
1048  }
1049  m_wifiPhy->m_currentEvent = nullptr;
1050  // Cancel preamble reception
1052  }
1053 }
1054 
1055 bool
1057 {
1058  WifiMode txMode = ppdu->GetTxVector().GetMode();
1059  if (!IsModeSupported(txMode))
1060  {
1061  NS_LOG_DEBUG("Drop packet because it was sent using an unsupported mode (" << txMode
1062  << ")");
1063  return false;
1064  }
1065  return true;
1066 }
1067 
1068 void
1070 {
1071  NS_LOG_FUNCTION(this);
1072  for (auto& endPreambleDetectionEvent : m_endPreambleDetectionEvents)
1073  {
1074  endPreambleDetectionEvent.Cancel();
1075  }
1077  for (auto& endRxPayloadEvent : m_endRxPayloadEvents)
1078  {
1079  endRxPayloadEvent.Cancel();
1080  }
1081  m_endRxPayloadEvents.clear();
1082  for (auto& endMpduEvent : m_endOfMpduEvents)
1083  {
1084  endMpduEvent.Cancel();
1085  }
1086  m_endOfMpduEvents.clear();
1087 }
1088 
1089 bool
1091 {
1092  return m_endPreambleDetectionEvents.empty();
1093 }
1094 
1095 void
1097 {
1098  NS_LOG_FUNCTION(this << clear);
1099  for (auto& endPreambleDetectionEvent : m_endPreambleDetectionEvents)
1100  {
1101  if (endPreambleDetectionEvent.IsRunning())
1102  {
1103  endPreambleDetectionEvent.Cancel();
1104  }
1105  }
1106  if (clear)
1107  {
1109  }
1110 }
1111 
1112 void
1114 {
1115  NS_LOG_FUNCTION(this << reason);
1116  DoAbortCurrentReception(reason);
1118 }
1119 
1120 void
1122 {
1123  NS_LOG_FUNCTION(this << reason);
1124  if (m_wifiPhy->m_currentEvent) // Otherwise abort has already been called just before
1125  {
1126  for (auto& endMpduEvent : m_endOfMpduEvents)
1127  {
1128  endMpduEvent.Cancel();
1129  }
1130  m_endOfMpduEvents.clear();
1131  }
1132 }
1133 
1134 void
1136 {
1137  NS_LOG_FUNCTION(this << *event);
1138  DoResetReceive(event);
1140  m_wifiPhy->m_interference->NotifyRxEnd(Simulator::Now());
1141  NS_ASSERT(m_endRxPayloadEvents.size() == 1 && m_endRxPayloadEvents.front().IsExpired());
1142  m_endRxPayloadEvents.clear();
1143  m_wifiPhy->m_currentEvent = nullptr;
1145  m_wifiPhy->SwitchMaybeToCcaBusy(event->GetPpdu());
1146 }
1147 
1148 void
1150 {
1151  NS_LOG_FUNCTION(this << *event);
1152  NS_ASSERT(event->GetEndTime() == Simulator::Now());
1153 }
1154 
1155 double
1157 {
1158  return m_wifiPhy->m_random->GetValue();
1159 }
1160 
1161 double
1163 {
1164  return event->GetRxPowerW(GetPrimaryBand(GetMeasurementChannelWidth(event->GetPpdu())));
1165 }
1166 
1169 {
1170  return m_wifiPhy->m_currentEvent;
1171 }
1172 
1174 PhyEntity::GetPrimaryBand(uint16_t bandWidth) const
1175 {
1176  if (m_wifiPhy->GetChannelWidth() % 20 != 0)
1177  {
1178  return m_wifiPhy->GetBand(bandWidth);
1179  }
1180  return m_wifiPhy->GetBand(bandWidth,
1182 }
1183 
1185 PhyEntity::GetSecondaryBand(uint16_t bandWidth) const
1186 {
1188  return m_wifiPhy->GetBand(bandWidth,
1190 }
1191 
1192 uint16_t
1194 {
1195  return std::min(m_wifiPhy->GetChannelWidth(), txVector.GetChannelWidth());
1196 }
1197 
1198 double
1200  WifiChannelListType /*channelType*/) const
1201 {
1203 }
1204 
1205 Time
1207 {
1208  return m_wifiPhy->m_interference->GetEnergyDuration(DbmToW(thresholdDbm), band);
1209 }
1210 
1211 void
1213 {
1214  // We are here because we have received the first bit of a packet and we are
1215  // not going to be able to synchronize on it
1216  // In this model, CCA becomes busy when the aggregation of all signals as
1217  // tracked by the InterferenceHelper class is higher than the CcaBusyThreshold
1218  const auto ccaIndication = GetCcaIndication(ppdu);
1219  if (ccaIndication.has_value())
1220  {
1221  NS_LOG_DEBUG("CCA busy for " << ccaIndication.value().second << " during "
1222  << ccaIndication.value().first.As(Time::S));
1223  m_state->SwitchMaybeToCcaBusy(ccaIndication.value().first,
1224  ccaIndication.value().second,
1225  {});
1226  return;
1227  }
1228  if (ppdu)
1229  {
1230  SwitchMaybeToCcaBusy(nullptr);
1231  }
1232 }
1233 
1236 {
1237  const uint16_t channelWidth = GetMeasurementChannelWidth(ppdu);
1238  NS_LOG_FUNCTION(this << channelWidth);
1239  const double ccaThresholdDbm = GetCcaThreshold(ppdu, WIFI_CHANLIST_PRIMARY);
1240  const Time delayUntilCcaEnd =
1241  GetDelayUntilCcaEnd(ccaThresholdDbm, GetPrimaryBand(channelWidth));
1242  if (delayUntilCcaEnd.IsStrictlyPositive())
1243  {
1244  return std::make_pair(delayUntilCcaEnd, WIFI_CHANLIST_PRIMARY);
1245  }
1246  return std::nullopt;
1247 }
1248 
1249 void
1251  Time duration,
1252  WifiChannelListType channelType)
1253 {
1254  NS_LOG_FUNCTION(this << duration << channelType);
1255  NS_LOG_DEBUG("CCA busy for " << channelType << " during " << duration.As(Time::S));
1256  m_state->SwitchMaybeToCcaBusy(duration, channelType, {});
1257 }
1258 
1259 uint64_t
1261 {
1262  NS_LOG_FUNCTION(this);
1263  return m_globalPpduUid++;
1264 }
1265 
1266 uint16_t
1268 {
1269  NS_LOG_FUNCTION(this << txVector);
1270 
1272  txVector.GetChannelWidth());
1273 }
1274 
1275 void
1276 PhyEntity::NotifyPayloadBegin(const WifiTxVector& txVector, const Time& payloadDuration)
1277 {
1278  m_wifiPhy->m_phyRxPayloadBeginTrace(txVector, payloadDuration);
1279 }
1280 
1281 void
1283 {
1284  NS_LOG_FUNCTION(this << ppdu);
1285  auto txPowerDbm = m_wifiPhy->GetTxPowerForTransmission(ppdu) + m_wifiPhy->GetTxGain();
1286  auto txVector = ppdu->GetTxVector();
1287  auto txPowerSpectrum = GetTxPowerSpectralDensity(DbmToW(txPowerDbm), ppdu);
1288  Transmit(ppdu->GetTxDuration(), ppdu, txPowerDbm, txPowerSpectrum, "transmission");
1289 }
1290 
1291 void
1293  Ptr<const WifiPpdu> ppdu,
1294  double txPowerDbm,
1295  Ptr<SpectrumValue> txPowerSpectrum,
1296  const std::string& type)
1297 {
1298  NS_LOG_FUNCTION(this << txDuration << ppdu << txPowerDbm << type);
1299  NS_LOG_DEBUG("Start " << type << ": signal power before antenna gain=" << txPowerDbm << "dBm");
1300  auto txParams = Create<WifiSpectrumSignalParameters>();
1301  txParams->duration = txDuration;
1302  txParams->psd = txPowerSpectrum;
1303  txParams->ppdu = ppdu;
1304  txParams->txWidth = ppdu->GetTxVector().GetChannelWidth();
1305  ;
1306  NS_LOG_DEBUG("Starting " << type << " with power " << txPowerDbm << " dBm on channel "
1307  << +m_wifiPhy->GetChannelNumber() << " for "
1308  << txParams->duration.As(Time::MS));
1309  NS_LOG_DEBUG("Starting " << type << " with integrated spectrum power "
1310  << WToDbm(Integral(*txPowerSpectrum)) << " dBm; spectrum model Uid: "
1311  << txPowerSpectrum->GetSpectrumModel()->GetUid());
1312  auto spectrumWifiPhy = DynamicCast<SpectrumWifiPhy>(m_wifiPhy);
1313  NS_ASSERT(spectrumWifiPhy);
1314  spectrumWifiPhy->Transmit(txParams);
1315 }
1316 
1317 uint16_t
1318 PhyEntity::GetGuardBandwidth(uint16_t currentChannelWidth) const
1319 {
1320  return m_wifiPhy->GetGuardBandwidth(currentChannelWidth);
1321 }
1322 
1323 std::tuple<double, double, double>
1325 {
1327 }
1328 
1329 Time
1331  const WifiTxVector& txVector,
1332  WifiPhyBand band) const
1333 {
1334  NS_ASSERT(psduMap.size() == 1);
1335  const auto& it = psduMap.begin();
1336  return WifiPhy::CalculateTxDuration(it->second->GetSize(), txVector, band, it->first);
1337 }
1338 
1339 bool
1340 PhyEntity::CanStartRx(Ptr<const WifiPpdu> ppdu, uint16_t txChannelWidth) const
1341 {
1342  // The PHY shall not issue a PHY-RXSTART.indication primitive in response to a PPDU that does
1343  // not overlap the primary channel
1344  const auto channelWidth = m_wifiPhy->GetChannelWidth();
1345  const auto primaryWidth =
1346  ((channelWidth % 20 == 0) ? 20
1347  : channelWidth); // if the channel width is a multiple of 20 MHz,
1348  // then we consider the primary20 channel
1349  const auto p20CenterFreq =
1351  const auto p20MinFreq = p20CenterFreq - (primaryWidth / 2);
1352  const auto p20MaxFreq = p20CenterFreq + (primaryWidth / 2);
1353  const auto txCenterFreq = ppdu->GetTxCenterFreq();
1354  const auto minTxFreq = txCenterFreq - txChannelWidth / 2;
1355  const auto maxTxFreq = txCenterFreq + txChannelWidth / 2;
1356  if (p20MinFreq < minTxFreq || p20MaxFreq > maxTxFreq)
1357  {
1358  return false;
1359  }
1360  return true;
1361 }
1362 
1365 {
1366  return ppdu;
1367 }
1368 
1369 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsExpired() const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:69
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
void NotifyPayloadBegin(const WifiTxVector &txVector, const Time &payloadDuration)
Fire the trace indicating that the PHY is starting to receive the payload of a PPDU.
Definition: phy-entity.cc:1276
void DropPreambleEvent(Ptr< const WifiPpdu > ppdu, WifiPhyRxfailureReason reason, Time endRx)
Drop the PPDU and the corresponding preamble detection event, but keep CCA busy state after the compl...
Definition: phy-entity.cc:527
std::list< WifiMode >::const_iterator end() const
Return a const iterator to past-the-last WifiMode.
Definition: phy-entity.cc:144
virtual const PpduFormats & GetPpduFormats() const =0
Return the PPDU formats of the PHY.
virtual void RxPayloadSucceeded(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, uint16_t staId, const std::vector< bool > &statusPerMpdu)
Perform amendment-specific actions when the payload is successfully received.
Definition: phy-entity.cc:754
virtual PhyFieldRxStatus DoEndReceivePreamble(Ptr< Event > event)
End receiving the preamble, perform amendment-specific actions, and provide the status of the recepti...
Definition: phy-entity.cc:900
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper of the WifiPhy (to make it reachable for child classes)
Definition: phy-entity.h:964
virtual void RxPayloadFailed(Ptr< const WifiPsdu > psdu, double snr, const WifiTxVector &txVector)
Perform amendment-specific actions when the payload is unsuccessfuly received.
Definition: phy-entity.cc:766
void EndPreambleDetectionPeriod(Ptr< Event > event)
End the preamble detection period.
Definition: phy-entity.cc:924
virtual void NotifyCcaBusy(const Ptr< const WifiPpdu > ppdu, Time duration, WifiChannelListType channelType)
Notify PHY state helper to switch to CCA busy state,.
Definition: phy-entity.cc:1250
virtual Ptr< WifiPpdu > BuildPpdu(const WifiConstPsduMap &psdus, const WifiTxVector &txVector, Time ppduDuration)
Build amendment-specific PPDU.
Definition: phy-entity.cc:242
virtual Time GetDuration(WifiPpduField field, const WifiTxVector &txVector) const
Get the duration of the PPDU field (or group of fields) used by this entity for the given transmissio...
Definition: phy-entity.cc:190
std::tuple< double, double, double > GetTxMaskRejectionParams() const
Definition: phy-entity.cc:1324
virtual uint64_t ObtainNextUid(const WifiTxVector &txVector)
Obtain the next UID for the PPDU to transmit.
Definition: phy-entity.cc:1260
virtual Time DoStartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
Definition: phy-entity.cc:584
virtual bool CanStartRx(Ptr< const WifiPpdu > ppdu, uint16_t txChannelWidth) const
Determine whether the PHY shall issue a PHY-RXSTART.indication primitive in response to a given PPDU.
Definition: phy-entity.cc:1340
virtual void StartReceivePreamble(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW, Time rxDuration)
Start receiving the PHY preamble of a PPDU (i.e.
Definition: phy-entity.cc:399
Ptr< Event > CreateInterferenceEvent(Ptr< const WifiPpdu > ppdu, const WifiTxVector &txVector, Time duration, RxPowerWattPerChannelBand &rxPower, bool isStartOfdmaRxing=false)
Create an event using WifiPhy's InterferenceHelper class.
Definition: phy-entity.cc:867
bool NoEndPreambleDetectionEvents() const
Definition: phy-entity.cc:1090
virtual Ptr< SpectrumValue > GetTxPowerSpectralDensity(double txPowerW, Ptr< const WifiPpdu > ppdu) const =0
virtual bool HandlesMcsModes() const
Check if the WifiModes handled by this PHY are MCSs.
Definition: phy-entity.cc:132
const std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents() const
Get the map of current preamble events (stored in WifiPhy).
Definition: phy-entity.cc:837
std::map< UidStaIdPair, SignalNoiseDbm > m_signalNoiseMap
Map of the latest signal power and noise power in dBm (noise power includes the noise figure)
Definition: phy-entity.h:984
Ptr< WifiPhy > m_wifiPhy
Pointer to the owning WifiPhy.
Definition: phy-entity.h:963
void Transmit(Time txDuration, Ptr< const WifiPpdu > ppdu, double txPowerDbm, Ptr< SpectrumValue > txPowerSpectrum, const std::string &type)
This function prepares most of the WifiSpectrumSignalParameters parameters and invokes SpectrumWifiPh...
Definition: phy-entity.cc:1292
WifiSpectrumBand GetSecondaryBand(uint16_t bandWidth) const
If the channel bonding is used, return the start band index and the stop band index for the secondary...
Definition: phy-entity.cc:1185
std::vector< EventId > m_endOfMpduEvents
the end of MPDU events (only used for A-MPDUs)
Definition: phy-entity.h:970
virtual uint16_t GetMeasurementChannelWidth(const Ptr< const WifiPpdu > ppdu) const =0
Return the channel width used to measure the RSSI.
virtual std::pair< uint16_t, WifiSpectrumBand > GetChannelWidthAndBand(const WifiTxVector &txVector, uint16_t staId) const
Get the channel width and band to use (will be overloaded by child classes).
Definition: phy-entity.cc:830
virtual ~PhyEntity()
Destructor for PHY entity.
Definition: phy-entity.cc:81
virtual double GetCcaThreshold(const Ptr< const WifiPpdu > ppdu, WifiChannelListType channelType) const
Return the CCA threshold in dBm for a given channel type.
Definition: phy-entity.cc:1199
virtual uint8_t GetNumModes() const
Definition: phy-entity.cc:110
virtual bool DoStartReceiveField(WifiPpduField field, Ptr< Event > event)
Start receiving a given field, perform amendment-specific actions, and signify if it is supported.
Definition: phy-entity.cc:368
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition: phy-entity.cc:89
std::list< WifiMode >::const_iterator begin() const
Return a const iterator to the first WifiMode.
Definition: phy-entity.cc:138
virtual void CancelAllEvents()
Cancel and clear all running events.
Definition: phy-entity.cc:1069
virtual void DoAbortCurrentReception(WifiPhyRxfailureReason reason)
Perform amendment-specific actions before aborting the current reception.
Definition: phy-entity.cc:1121
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Abort the current reception.
Definition: phy-entity.cc:1113
void EndReceivePayload(Ptr< Event > event)
The last symbol of the PPDU has arrived.
Definition: phy-entity.cc:705
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:987
PhyHeaderSections GetPhyHeaderSections(const WifiTxVector &txVector, Time ppduStart) const
Return a map of PHY header chunk information per PPDU field.
Definition: phy-entity.cc:223
virtual bool IsMcsSupported(uint8_t index) const
Check if the WifiMode corresponding to the given MCS index is supported.
Definition: phy-entity.cc:124
void StartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
Definition: phy-entity.cc:574
std::vector< EventId > m_endRxPayloadEvents
the end of receive events (only one unless UL MU reception)
Definition: phy-entity.h:973
virtual void DoResetReceive(Ptr< Event > event)
Perform amendment-specific actions before resetting PHY at the end of the PPDU under reception after ...
Definition: phy-entity.cc:1149
void EndReceiveField(WifiPpduField field, Ptr< Event > event)
End receiving a given field.
Definition: phy-entity.cc:308
virtual Ptr< Event > DoGetEvent(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW)
Get the event corresponding to the incoming PPDU.
Definition: phy-entity.cc:852
virtual WifiMode GetSigMode(WifiPpduField field, const WifiTxVector &txVector) const
Get the WifiMode for the SIG field specified by the PPDU field.
Definition: phy-entity.cc:150
WifiPpduField GetNextField(WifiPpduField currentField, WifiPreamble preamble) const
Return the field following the provided one.
Definition: phy-entity.cc:159
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Definition: phy-entity.h:327
double GetRxPowerWForPpdu(Ptr< Event > event) const
Obtain the received power (W) for a given band.
Definition: phy-entity.cc:1162
virtual void SwitchMaybeToCcaBusy(const Ptr< const WifiPpdu > ppdu)
Check if PHY state should move to CCA busy state based on current state of interference tracker.
Definition: phy-entity.cc:1212
Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector) const
Definition: phy-entity.cc:200
void NotifyInterferenceRxEndAndClear(bool reset)
Notify WifiPhy's InterferenceHelper of the end of the reception, clear maps and end of MPDU event,...
Definition: phy-entity.cc:883
void StartPreambleDetectionPeriod(Ptr< Event > event)
Start the preamble detection period.
Definition: phy-entity.cc:910
Time GetDurationUpToField(WifiPpduField field, const WifiTxVector &txVector) const
Get the duration of the PPDU up to (but excluding) the given field.
Definition: phy-entity.cc:254
std::map< UidStaIdPair, std::vector< bool > > m_statusPerMpduMap
Map of the current reception status per MPDU that is filled in as long as MPDUs are being processed b...
Definition: phy-entity.h:981
virtual void StartTx(Ptr< const WifiPpdu > ppdu)
This function is called by SpectrumWifiPhy to send the PPDU while performing amendment-specific actio...
Definition: phy-entity.cc:1282
virtual uint16_t GetRxChannelWidth(const WifiTxVector &txVector) const
Return the channel width used in the reception spectrum model.
Definition: phy-entity.cc:1193
Time GetDelayUntilCcaEnd(double thresholdDbm, WifiSpectrumBand band)
Return the delay until CCA busy is ended for a given sensitivity threshold (in dBm) and a given band.
Definition: phy-entity.cc:1206
void CancelRunningEndPreambleDetectionEvents(bool clear=false)
Cancel and eventually clear all end preamble detection events.
Definition: phy-entity.cc:1096
Time GetRemainingDurationAfterField(Ptr< const WifiPpdu > ppdu, WifiPpduField field) const
Get the remaining duration of the PPDU after the end of the given field.
Definition: phy-entity.cc:360
virtual uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const
Return the STA ID that has been assigned to the station this PHY belongs to.
Definition: phy-entity.cc:568
virtual Time CalculateTxDuration(WifiConstPsduMap psduMap, const WifiTxVector &txVector, WifiPhyBand band) const
Definition: phy-entity.cc:1330
void StartReceiveField(WifiPpduField field, Ptr< Event > event)
Start receiving a given field.
Definition: phy-entity.cc:281
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const
Definition: phy-entity.cc:1318
virtual bool IsModeSupported(WifiMode mode) const
Check if the WifiMode is supported.
Definition: phy-entity.cc:97
void ResetReceive(Ptr< Event > event)
Reset PHY at the end of the PPDU under reception after it has failed the PHY header.
Definition: phy-entity.cc:1135
std::optional< std::pair< Time, WifiChannelListType > > CcaIndication
CCA end time and its corresponding channel list type (can be std::nullopt if IDLE)
Definition: phy-entity.h:951
virtual CcaIndication GetCcaIndication(const Ptr< const WifiPpdu > ppdu)
Get CCA end time and its corresponding channel list type when a new signal has been received by the P...
Definition: phy-entity.cc:1235
std::list< WifiMode > m_modeList
the list of supported modes
Definition: phy-entity.h:967
Ptr< const Event > GetCurrentEvent() const
Get the pointer to the current event (stored in WifiPhy).
Definition: phy-entity.cc:1168
double GetRandomValue() const
Obtain a random value from the WifiPhy's generator.
Definition: phy-entity.cc:1156
std::vector< EventId > m_endPreambleDetectionEvents
the end of preamble detection events
Definition: phy-entity.h:969
virtual Ptr< const WifiPsdu > GetAddressedPsduInPpdu(Ptr< const WifiPpdu > ppdu) const
Get the PSDU addressed to that PHY in a PPDU (useful for MU PPDU).
Definition: phy-entity.cc:217
SnrPer GetPhyHeaderSnrPer(WifiPpduField field, Ptr< Event > event) const
Obtain the SNR and PER of the PPDU field from the WifiPhy's InterferenceHelper class.
Definition: phy-entity.cc:270
void ErasePreambleEvent(Ptr< const WifiPpdu > ppdu, Time rxDuration)
Erase the event corresponding to the PPDU from the list of preamble events, but consider it as noise ...
Definition: phy-entity.cc:546
virtual Ptr< const WifiPpdu > GetRxPpduFromTxPpdu(Ptr< const WifiPpdu > ppdu)
The WifiPpdu from the TX PHY is received by each RX PHY attached to the same channel.
Definition: phy-entity.cc:1364
virtual WifiMode GetMcs(uint8_t index) const
Get the WifiMode corresponding to the given MCS index.
Definition: phy-entity.cc:116
void AddPreambleEvent(Ptr< Event > event)
Add an entry to the map of current preamble events (stored in WifiPhy).
Definition: phy-entity.cc:843
virtual void DoEndReceivePayload(Ptr< const WifiPpdu > ppdu)
Perform amendment-specific actions at the end of the reception of the payload.
Definition: phy-entity.cc:774
uint16_t GetCenterFrequencyForChannelWidth(const WifiTxVector &txVector) const
Get the center frequency of the channel corresponding the current TxVector rather than that of the su...
Definition: phy-entity.cc:1267
virtual WifiConstPsduMap GetWifiConstPsduMap(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) const
Get a WifiConstPsduMap from a PSDU and the TXVECTOR to use to send the PSDU.
Definition: phy-entity.cc:211
virtual bool IsConfigSupported(Ptr< const WifiPpdu > ppdu) const
Checks if the signaled configuration (excluding bandwidth) is supported by the PHY.
Definition: phy-entity.cc:1056
WifiSpectrumBand GetPrimaryBand(uint16_t bandWidth) const
If the operating channel width is a multiple of 20 MHz, return the start band index and the stop band...
Definition: phy-entity.cc:1174
PhyRxFailureAction
Action to perform in case of RX failure.
Definition: phy-entity.h:103
@ DROP
drop PPDU and set CCA_BUSY
Definition: phy-entity.h:104
@ IGNORE
ignore the reception
Definition: phy-entity.h:106
@ ABORT
abort reception of PPDU
Definition: phy-entity.h:105
void UpdateInterferenceEvent(Ptr< Event > event, const RxPowerWattPerChannelBand &rxPower)
Update an event in WifiPhy's InterferenceHelper class.
Definition: phy-entity.cc:877
std::pair< bool, SignalNoiseDbm > GetReceptionStatus(Ptr< const WifiPsdu > psdu, Ptr< Event > event, uint16_t staId, Time relativeMpduStart, Time mpduDuration)
Get the reception status for the provided MPDU and notify.
Definition: phy-entity.cc:786
void EndOfMpdu(Ptr< Event > event, Ptr< const WifiPsdu > psdu, size_t mpduIndex, Time relativeStart, Time mpduDuration)
The last symbol of an MPDU in an A-MPDU has arrived.
Definition: phy-entity.cc:668
virtual PhyFieldRxStatus DoEndReceiveField(WifiPpduField field, Ptr< Event > event)
End receiving a given field, perform amendment-specific actions, and provide the status of the recept...
Definition: phy-entity.cc:387
void ScheduleEndOfMpdus(Ptr< Event > event)
Schedule end of MPDUs events.
Definition: phy-entity.cc:606
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
SpectrumModelUid_t GetUid() const
Ptr< const SpectrumModel > GetSpectrumModel() const
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
@ MS
millisecond
Definition: nstime.h:117
@ S
second
Definition: nstime.h:116
@ NS
nanosecond
Definition: nstime.h:119
bool IsZero() const
Exactly equivalent to t == 0.
Definition: nstime.h:314
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
represent a single transmission mode
Definition: wifi-mode.h:50
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:122
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper.
Definition: wifi-phy.h:1209
double GetCcaEdThreshold() const
Return the CCA energy detection threshold (dBm).
Definition: wifi-phy.cc:492
Ptr< UniformRandomVariable > m_random
Provides uniform random variables.
Definition: wifi-phy.h:1208
void NotifyCcaBusy(const Ptr< const WifiPpdu > ppdu, Time duration)
Notify PHY state helper to switch to CCA busy state,.
Definition: wifi-phy.cc:2065
WifiPhyOperatingChannel m_operatingChannel
Operating channel.
Definition: wifi-phy.h:1439
static Time GetPayloadDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, MpduType mpdutype=NORMAL_MPDU, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1433
uint16_t GetChannelWidth() const
Definition: wifi-phy.cc:1026
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > m_currentPreambleEvents
store event associated to a PPDU (that has a unique ID and preamble combination) whose preamble is be...
Definition: wifi-phy.h:1221
EventId m_endPhyRxEvent
the end of PHY receive event
Definition: wifi-phy.h:1216
double GetTxGain() const
Return the transmission gain (dB).
Definition: wifi-phy.cc:568
void NotifyRxDrop(Ptr< const WifiPsdu > psdu, WifiPhyRxfailureReason reason)
Public method used to fire a PhyRxDrop trace.
Definition: wifi-phy.cc:1581
bool IsStateRx() const
Definition: wifi-phy.cc:2010
uint16_t GetFrequency() const
Definition: wifi-phy.cc:1014
static Time GetPreambleDetectionDuration()
Definition: wifi-phy.cc:1421
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Due to newly arrived signal, the current reception cannot be continued and has to be aborted.
Definition: wifi-phy.cc:2072
Ptr< FrameCaptureModel > m_frameCaptureModel
Frame capture model.
Definition: wifi-phy.h:1481
void NotifyRxBegin(Ptr< const WifiPsdu > psdu, const RxPowerWattPerChannelBand &rxPowersW)
Public method used to fire a PhyRxBegin trace.
Definition: wifi-phy.cc:1557
virtual std::tuple< double, double, double > GetTxMaskRejectionParams() const =0
virtual uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const =0
bool IsStateOff() const
Definition: wifi-phy.cc:2034
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1480
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1244
Ptr< ErrorModel > m_postReceptionErrorModel
Error model for receive packet events.
Definition: wifi-phy.h:1484
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:996
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1219
virtual WifiSpectrumBand GetBand(uint16_t bandWidth, uint8_t bandIndex=0)
Get the start band index and the stop band index for a given band.
Definition: wifi-phy.cc:2175
uint8_t GetChannelNumber() const
Return current channel number.
Definition: wifi-phy.cc:1020
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1224
Ptr< PreambleDetectionModel > m_preambleDetectionModel
Preamble detection model.
Definition: wifi-phy.h:1482
void NotifyRxEnd(Ptr< const WifiPsdu > psdu)
Public method used to fire a PhyRxEnd trace.
Definition: wifi-phy.cc:1569
bool IsStateSleep() const
Definition: wifi-phy.cc:2028
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1206
double GetTxPowerForTransmission(Ptr< const WifiPpdu > ppdu) const
Compute the transmit power for the next transmission.
Definition: wifi-phy.cc:2132
void NotifyMonitorSniffRx(Ptr< const WifiPsdu > psdu, uint16_t channelFreqMhz, WifiTxVector txVector, SignalNoiseDbm signalNoise, std::vector< bool > statusPerMpdu, uint16_t staId=SU_STA_ID)
Public method used to fire a MonitorSniffer trace for a wifi PSDU being received.
Definition: wifi-phy.cc:1593
Ptr< PhyEntity > GetPhyEntityForPpdu(const Ptr< const WifiPpdu > ppdu) const
Get the supported PHY entity to use for a received PPDU.
Definition: wifi-phy.cc:725
void Reset()
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1804
TracedCallback< WifiTxVector, Time > m_phyRxPayloadBeginTrace
The trace source fired when the reception of the PHY payload (PSDU) begins.
Definition: wifi-phy.h:1371
Time GetLastRxEndTime() const
Return the end time of the last received packet.
Definition: wifi-phy.cc:2052
Time m_timeLastPreambleDetected
Record the time the last preamble was detected.
Definition: wifi-phy.h:1485
void SwitchMaybeToCcaBusy(const Ptr< const WifiPpdu > ppdu)
Check if PHY state should move to CCA busy state based on current state of interference tracker.
Definition: wifi-phy.cc:2058
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1008
double GetCcaSensitivityThreshold() const
Return the CCA sensitivity threshold (dBm).
Definition: wifi-phy.cc:505
uint8_t GetPrimaryChannelIndex(uint16_t primaryChannelWidth) const
If the operating channel width is a multiple of 20 MHz, return the index of the primary channel of th...
uint8_t GetSecondaryChannelIndex(uint16_t secondaryChannelWidth) const
If the operating channel width is made of a multiple of 20 MHz, return the index of the secondary cha...
uint16_t GetPrimaryChannelCenterFrequency(uint16_t primaryChannelWidth) const
Get the center frequency of the primary channel of the given width.
Ptr< const Packet > GetPacket() const
Get the PSDU as a single packet.
Definition: wifi-psdu.cc:89
std::vector< Ptr< WifiMpdu > >::const_iterator end() const
Return a const iterator to past-the-last MPDU.
Definition: wifi-psdu.cc:345
std::vector< Ptr< WifiMpdu > >::const_iterator begin() const
Return a const iterator to the first MPDU.
Definition: wifi-psdu.cc:333
uint32_t GetSize() const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:273
std::size_t GetAmpduSubframeSize(std::size_t i) const
Return the size of the i-th A-MPDU subframe.
Definition: wifi-psdu.cc:314
bool IsSingle() const
Return true if the PSDU is an S-MPDU.
Definition: wifi-psdu.cc:77
std::size_t GetNMpdus() const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:327
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint16_t GetGuardInterval() const
WifiPreamble GetPreambleType() const
uint8_t GetNss(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the number of spatial streams.
uint16_t GetChannelWidth() const
#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_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#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(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1360
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiPhyBand
Identifies the PHY band.
Definition: wifi-phy-band.h:33
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
WifiPpduField
The type of PPDU field (grouped for convenience)
MpduType
The type of an MPDU.
@ PREAMBLE_DETECT_FAILURE
@ TRUNCATED_TX
@ FRAME_CAPTURE_PACKET_SWITCH
@ POWERED_OFF
@ CHANNEL_SWITCHING
@ BUSY_DECODING_PREAMBLE
@ PREAMBLE_DETECTION_PACKET_SWITCH
@ WIFI_CHANLIST_PRIMARY
@ WIFI_PPDU_FIELD_EHT_SIG
EHT-SIG field.
@ WIFI_PPDU_FIELD_PREAMBLE
SYNC + SFD fields for DSSS or ERP, shortSYNC + shortSFD fields for HR/DSSS or ERP,...
@ WIFI_PPDU_FIELD_DATA
data field
@ LAST_MPDU_IN_AGGREGATE
The MPDU is the last aggregate in an A-MPDU with multiple MPDUs.
@ NORMAL_MPDU
The MPDU is not part of an A-MPDU.
@ FIRST_MPDU_IN_AGGREGATE
The MPDU is the first aggregate in an A-MPDU with multiple MPDUs, but is not the last aggregate.
@ SINGLE_MPDU
The MPDU is a single MPDU.
@ MIDDLE_MPDU_IN_AGGREGATE
The MPDU is part of an A-MPDU with multiple MPDUs, but is neither the first nor the last aggregate.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double RatioToDb(double ratio)
Convert from ratio to dB.
Definition: wifi-utils.cc:52
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
double WToDbm(double w)
Convert from Watts to dBm.
Definition: wifi-utils.cc:46
std::pair< uint32_t, uint32_t > WifiSpectrumBand
typedef for a pair of start and stop sub-band indexes
double Integral(const SpectrumValue &arg)
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:40
std::map< WifiSpectrumBand, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Definition: phy-entity.h:78
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:129
Declaration of:
Status of the reception of the PPDU field.
Definition: phy-entity.h:113
WifiPhyRxfailureReason reason
failure reason
Definition: phy-entity.h:115
PhyRxFailureAction actionIfFailure
action to perform in case of failure
Definition: phy-entity.h:116
bool isSuccess
outcome (true if success) of the reception
Definition: phy-entity.h:114
A struct for both SNR and PER.
Definition: phy-entity.h:148
double snr
SNR in linear scale.
Definition: phy-entity.h:149
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:70
double rssi
RSSI in dBm.
Definition: phy-entity.h:72
double snr
SNR in linear scale.
Definition: phy-entity.h:71
SignalNoiseDbm structure.
Definition: phy-entity.h:56
double noise
noise power in dBm
Definition: phy-entity.h:58
double signal
signal strength in dBm
Definition: phy-entity.h:57
#define SU_STA_ID
Definition: wifi-mode.h:34
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ SWITCHING
The PHY layer is switching to other channel.
@ RX
The PHY layer is receiving a packet.
@ TX
The PHY layer is sending a packet.
@ OFF
The PHY layer is switched off.
@ SLEEP
The PHY layer is sleeping.
@ IDLE
The PHY layer is IDLE.