A Discrete-Event Network Simulator
API
phy-entity.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 Orange Labs
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Rediet <getachew.redieteab@orange.com>
19  * Sébastien Deronne <sebastien.deronne@gmail.com> (for logic ported from wifi-phy and spectrum-wifi-phy)
20  * Mathieu Lacage <mathieu.lacage@sophia.inria.fr> (for logic ported from wifi-phy)
21  */
22 
23 #include "phy-entity.h"
24 #include "spectrum-wifi-phy.h"
25 #include "wifi-psdu.h"
27 #include "frame-capture-model.h"
28 #include "wifi-utils.h"
30 #include "interference-helper.h"
31 #include "ns3/packet.h"
32 #include "ns3/simulator.h"
33 #include "ns3/log.h"
34 #include "ns3/assert.h"
35 #include <algorithm>
36 
37 namespace ns3 {
38 
39 NS_LOG_COMPONENT_DEFINE ("PhyEntity");
40 
41 std::ostream & operator << (std::ostream &os, const PhyEntity::PhyRxFailureAction &action)
42 {
43  switch (action)
44  {
45  case PhyEntity::DROP:
46  return (os << "DROP");
47  case PhyEntity::ABORT:
48  return (os << "ABORT");
49  case PhyEntity::IGNORE:
50  return (os << "IGNORE");
51  default:
52  NS_FATAL_ERROR ("Unknown action");
53  return (os << "unknown");
54  }
55 }
56 
57 std::ostream & operator << (std::ostream &os, const PhyEntity::PhyFieldRxStatus &status)
58 {
59  if (status.isSuccess)
60  {
61  return os << "success";
62  }
63  else
64  {
65  return os << "failure (" << status.reason << "/" << status.actionIfFailure << ")";
66  }
67 }
68 
69 /*******************************************************
70  * Abstract base class for PHY entities
71  *******************************************************/
72 
73 uint64_t PhyEntity::m_globalPpduUid = 0;
74 
76 {
77  NS_LOG_FUNCTION (this);
78  m_modeList.clear ();
79  CancelAllEvents ();
80 }
81 
82 void
84 {
85  NS_LOG_FUNCTION (this << wifiPhy);
86  m_wifiPhy = wifiPhy;
88 }
89 
90 bool
92 {
93  for (const auto & m : m_modeList)
94  {
95  if (m == mode)
96  {
97  return true;
98  }
99  }
100  return false;
101 }
102 
103 uint8_t
105 {
106  return m_modeList.size ();
107 }
108 
109 WifiMode
110 PhyEntity::GetMcs (uint8_t /* index */) const
111 {
112  NS_ABORT_MSG ("This method should be used only for HtPhy and child classes. Use GetMode instead.");
113  return WifiMode ();
114 }
115 
116 bool
117 PhyEntity::IsMcsSupported (uint8_t /* index */) const
118 {
119  NS_ABORT_MSG ("This method should be used only for HtPhy and child classes. Use IsModeSupported instead.");
120  return false;
121 }
122 
123 bool
125 {
126  return false;
127 }
128 
129 std::list<WifiMode>::const_iterator
130 PhyEntity::begin (void) const
131 {
132  return m_modeList.begin ();
133 }
134 
135 std::list<WifiMode>::const_iterator
136 PhyEntity::end (void) const
137 {
138  return m_modeList.end ();
139 }
140 
141 WifiMode
142 PhyEntity::GetSigMode (WifiPpduField field, const WifiTxVector& txVector) const
143 {
144  NS_FATAL_ERROR ("PPDU field is not a SIG field (no sense in retrieving the signaled mode) or is unsupported: " << field);
145  return WifiMode (); //should be overloaded
146 }
147 
149 PhyEntity::GetNextField (WifiPpduField currentField, WifiPreamble preamble) const
150 {
151  auto ppduFormats = GetPpduFormats ();
152  const auto itPpdu = ppduFormats.find (preamble);
153  if (itPpdu != ppduFormats.end ())
154  {
155  const auto itField = std::find (itPpdu->second.begin (), itPpdu->second.end (), currentField);
156  if (itField != itPpdu->second.end ())
157  {
158  const auto itNextField = std::next (itField, 1);
159  if (itNextField != itPpdu->second.end ())
160  {
161  return *(itNextField);
162  }
163  NS_FATAL_ERROR ("No field after " << currentField << " for " << preamble << " for the provided PPDU formats");
164  }
165  else
166  {
167  NS_FATAL_ERROR ("Unsupported PPDU field " << currentField << " for " << preamble << " for the provided PPDU formats");
168  }
169  }
170  else
171  {
172  NS_FATAL_ERROR ("Unsupported preamble " << preamble << " for the provided PPDU formats");
173  }
174  return WifiPpduField::WIFI_PPDU_FIELD_PREAMBLE; // Silence compiler warning
175 }
176 
177 Time
178 PhyEntity::GetDuration (WifiPpduField field, const WifiTxVector& txVector) const
179 {
180  if (field > WIFI_PPDU_FIELD_SIG_B)
181  {
182  NS_FATAL_ERROR ("Unsupported PPDU field");
183  }
184  return MicroSeconds (0); //should be overloaded
185 }
186 
187 Time
189 {
190  Time duration = MicroSeconds (0);
191  for (uint8_t field = WIFI_PPDU_FIELD_PREAMBLE; field < WIFI_PPDU_FIELD_DATA; ++field)
192  {
193  duration += GetDuration (static_cast<WifiPpduField> (field), txVector);
194  }
195  return duration;
196 }
197 
200 {
201  return WifiConstPsduMap ({std::make_pair (SU_STA_ID, psdu)});
202 }
203 
206 {
207  return ppdu->GetPsdu ();
208 }
209 
211 PhyEntity::GetPhyHeaderSections (const WifiTxVector& txVector, Time ppduStart) const
212 {
213  PhyHeaderSections map;
214  WifiPpduField field = WIFI_PPDU_FIELD_PREAMBLE; //preamble always present
215  Time start = ppduStart;
216 
217  while (field != WIFI_PPDU_FIELD_DATA)
218  {
219  Time duration = GetDuration (field, txVector);
220  map[field] = std::make_pair (std::make_pair (start, start + duration),
221  GetSigMode (field, txVector));
222  //Move to next field
223  start += duration;
224  field = GetNextField (field, txVector.GetPreambleType ());
225  }
226  return map;
227 }
228 
230 PhyEntity::BuildPpdu (const WifiConstPsduMap & psdus, const WifiTxVector& txVector, Time /* ppduDuration */)
231 {
232  NS_LOG_FUNCTION (this << psdus << txVector);
233  NS_FATAL_ERROR ("This method is unsupported for the base PhyEntity class. Use the overloaded version in the amendment-specific subclasses instead!");
234  return Create<WifiPpdu> (psdus.begin ()->second, txVector); //should be overloaded
235 }
236 
237 Time
239 {
240  if (field == WIFI_PPDU_FIELD_DATA) //this field is not in the map returned by GetPhyHeaderSections
241  {
242  return CalculatePhyPreambleAndHeaderDuration (txVector);
243  }
244  const auto & sections = GetPhyHeaderSections (txVector, NanoSeconds (0));
245  auto it = sections.find (field);
246  NS_ASSERT (it != sections.end ());
247  const auto & startStopTimes = it->second.first;
248  return startStopTimes.first; //return the start time of field relatively to the beginning of the PPDU
249 }
250 
253 {
254  uint16_t measurementChannelWidth = GetMeasurementChannelWidth (event->GetPpdu ());
255  return m_wifiPhy->m_interference->CalculatePhyHeaderSnrPer (event, measurementChannelWidth, m_wifiPhy->GetPrimaryBand (measurementChannelWidth),
256  field);
257 }
258 
259 void
261 {
262  NS_LOG_FUNCTION (this << field << *event);
263  NS_ASSERT (m_wifiPhy); //no sense if no owner WifiPhy instance
265  NS_ABORT_MSG_IF (field == WIFI_PPDU_FIELD_PREAMBLE, "Use the StartReceivePreamble method for preamble reception");
266  //Handle special cases of data reception
267  if (field == WIFI_PPDU_FIELD_DATA)
268  {
269  StartReceivePayload (event);
270  return;
271  }
272 
273  bool supported = DoStartReceiveField (field, event);
274  NS_ABORT_MSG_IF (!supported, "Unknown field " << field << " for this PHY entity"); //TODO see what to do if not supported
275  Time duration = GetDuration (field, event->GetTxVector ());
276  m_wifiPhy->m_endPhyRxEvent = Simulator::Schedule (duration, &PhyEntity::EndReceiveField, this, field, event);
277  m_state->SwitchMaybeToCcaBusy (duration); //keep in CCA busy state up to reception of Data (will then switch to RX)
278 }
279 
280 void
282 {
283  NS_LOG_FUNCTION (this << field << *event);
284  NS_ASSERT (m_wifiPhy); //no sense if no owner WifiPhy instance
286  PhyFieldRxStatus status = DoEndReceiveField (field, event);
287  WifiTxVector txVector = event->GetTxVector ();
288  if (status.isSuccess) //move to next field if reception succeeded
289  {
290  StartReceiveField (GetNextField (field, txVector.GetPreambleType ()), event);
291  }
292  else
293  {
294  Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
295  switch (status.actionIfFailure)
296  {
297  case ABORT:
298  //Abort reception, but consider medium as busy
299  AbortCurrentReception (status.reason);
300  if (event->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
301  {
303  }
304  break;
305  case DROP:
306  //Notify drop, keep in CCA busy, and perform same processing as IGNORE case
307  if (status.reason == FILTERED)
308  {
309  //PHY-RXSTART is immediately followed by PHY-RXEND (Filtered)
310  m_wifiPhy->m_phyRxPayloadBeginTrace (txVector, NanoSeconds (0)); //this callback (equivalent to PHY-RXSTART primitive) is also triggered for filtered PPDUs
311  }
313  m_state->SwitchMaybeToCcaBusy (GetRemainingDurationAfterField (ppdu, field)); //keep in CCA busy state till the end
314  //no break
315  case IGNORE:
316  //Keep in Rx state and reset at end
318  &PhyEntity::ResetReceive, this, event));
319  break;
320  default:
321  NS_FATAL_ERROR ("Unknown action in case of failure");
322  }
323  }
324 }
325 
326 Time
328 {
329  const WifiTxVector& txVector = ppdu->GetTxVector ();
330  return ppdu->GetTxDuration () - (GetDurationUpToField (field, txVector) + GetDuration (field, txVector));
331 }
332 
333 bool
335 {
336  NS_LOG_FUNCTION (this << field << *event);
337  NS_ASSERT (field != WIFI_PPDU_FIELD_PREAMBLE && field != WIFI_PPDU_FIELD_DATA); //handled apart for the time being
338  auto ppduFormats = GetPpduFormats ();
339  auto itFormat = ppduFormats.find (event->GetPpdu ()->GetPreamble ());
340  if (itFormat != ppduFormats.end ())
341  {
342  auto itField = std::find (itFormat->second.begin (), itFormat->second.end (), field);
343  if (itField != itFormat->second.end ())
344  {
345  return true; //supported field so we can start receiving
346  }
347  }
348  return false; //unsupported otherwise
349 }
350 
353 {
354  NS_LOG_FUNCTION (this << field << *event);
355  NS_ASSERT (field != WIFI_PPDU_FIELD_DATA); //handled apart for the time being
356  if (field == WIFI_PPDU_FIELD_PREAMBLE)
357  {
358  return DoEndReceivePreamble (event);
359  }
360  return PhyFieldRxStatus (false); //failed reception by default
361 }
362 
363 void
365  Time rxDuration)
366 {
367  //The total RX power corresponds to the maximum over all the bands
368  auto it = std::max_element (rxPowersW.begin (), rxPowersW.end (),
369  [] (const std::pair<WifiSpectrumBand, double> &p1, const std::pair<WifiSpectrumBand, double> &p2) {
370  return p1.second < p2.second;
371  });
372  NS_LOG_FUNCTION (this << ppdu << it->second);
373 
374  Ptr<Event> event = DoGetEvent (ppdu, rxPowersW);
375  if (event == nullptr)
376  {
377  //PPDU should be simply considered as interference (once it has been accounted for in InterferenceHelper)
378  return;
379  }
380 
381  Time endRx = Simulator::Now () + rxDuration;
382  if (m_state->GetState () == WifiPhyState::OFF)
383  {
384  NS_LOG_DEBUG ("Cannot start RX because device is OFF");
385  if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
386  {
388  }
390  return;
391  }
392 
393  if (ppdu->IsTruncatedTx ())
394  {
395  NS_LOG_DEBUG ("Packet reception stopped because transmitter has been switched off");
396  if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
397  {
399  }
401  return;
402  }
403 
404  switch (m_state->GetState ())
405  {
407  NS_LOG_DEBUG ("Drop packet because of channel switching");
408  /*
409  * Packets received on the upcoming channel are added to the event list
410  * during the switching state. This way the medium can be correctly sensed
411  * when the device listens to the channel for the first time after the
412  * switching e.g. after channel switching, the channel may be sensed as
413  * busy due to other devices' transmissions started before the end of
414  * the switching.
415  */
417  break;
418  case WifiPhyState::RX:
421  && m_wifiPhy->m_frameCaptureModel->CaptureNewFrame (m_wifiPhy->m_currentEvent, event))
422  {
424  NS_LOG_DEBUG ("Switch to new packet");
426  }
427  else
428  {
429  NS_LOG_DEBUG ("Drop packet because already in Rx");
431  if (m_wifiPhy->m_currentEvent == 0)
432  {
433  /*
434  * We are here because the non-legacy PHY header has not been successfully received.
435  * The PHY is kept in RX state for the duration of the PPDU, but EndReceive function is
436  * not called when the reception of the PPDU is finished, which is responsible to clear
437  * m_currentPreambleEvents. As a result, m_currentPreambleEvents should be cleared here.
438  */
440  }
441  }
442  break;
443  case WifiPhyState::TX:
444  NS_LOG_DEBUG ("Drop packet because already in Tx");
446  break;
448  if (m_wifiPhy->m_currentEvent != 0)
449  {
452  && m_wifiPhy->m_frameCaptureModel->CaptureNewFrame (m_wifiPhy->m_currentEvent, event))
453  {
455  NS_LOG_DEBUG ("Switch to new packet");
457  }
458  else
459  {
460  NS_LOG_DEBUG ("Drop packet because already decoding preamble");
462  }
463  }
464  else
465  {
467  }
468  break;
469  case WifiPhyState::IDLE:
472  break;
473  case WifiPhyState::SLEEP:
474  NS_LOG_DEBUG ("Drop packet because in sleep mode");
476  break;
477  default:
478  NS_FATAL_ERROR ("Invalid WifiPhy state.");
479  break;
480  }
481 }
482 
483 void
484 PhyEntity::DropPreambleEvent (Ptr<const WifiPpdu> ppdu, WifiPhyRxfailureReason reason, Time endRx, uint16_t measurementChannelWidth)
485 {
486  NS_LOG_FUNCTION (this << ppdu << reason << endRx << measurementChannelWidth);
488  auto it = m_wifiPhy->m_currentPreambleEvents.find (std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()));
489  if (it != m_wifiPhy->m_currentPreambleEvents.end ())
490  {
492  }
493  if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
494  {
495  //that PPDU will be noise _after_ the end of the current event.
496  m_wifiPhy->SwitchMaybeToCcaBusy (measurementChannelWidth);
497  }
498 }
499 
500 void
502 {
503  NS_LOG_FUNCTION (this << ppdu << rxDuration);
504  auto it = m_wifiPhy->m_currentPreambleEvents.find (std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()));
505  if (it != m_wifiPhy->m_currentPreambleEvents.end ())
506  {
508  }
509  if (m_wifiPhy->m_currentPreambleEvents.empty ())
510  {
511  m_wifiPhy->Reset ();
512  }
513 
514  if (rxDuration > m_state->GetDelayUntilIdle ())
515  {
516  //this PPDU will be noise _after_ the completion of the current event
518  }
519 }
520 
521 uint16_t
522 PhyEntity::GetStaId (const Ptr<const WifiPpdu> /* ppdu */) const
523 {
524  return SU_STA_ID;
525 }
526 
527 void
529 {
530  NS_LOG_FUNCTION (this << *event);
532  const WifiTxVector& txVector = event->GetTxVector ();
533  Time payloadDuration = event->GetPpdu ()->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
534 
535  //TODO: Add method in WifiPhy to clear all other PHYs (since this one is starting Rx)
536  m_state->SwitchToRx (payloadDuration);
537  m_wifiPhy->m_phyRxPayloadBeginTrace (txVector, payloadDuration); //this callback (equivalent to PHY-RXSTART primitive) is triggered only if headers have been correctly decoded and that the mode within is supported
538 
539  DoStartReceivePayload (event);
540 }
541 
542 void
544 {
545  NS_LOG_FUNCTION (this << *event);
546  Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
547  NS_LOG_DEBUG ("Receiving PSDU");
548  uint16_t staId = GetStaId (ppdu);
549  m_signalNoiseMap.insert ({std::make_pair (ppdu->GetUid (), staId), SignalNoiseDbm ()});
550  m_statusPerMpduMap.insert ({std::make_pair (ppdu->GetUid (), staId), std::vector<bool> ()});
551  ScheduleEndOfMpdus (event);
552  m_endRxPayloadEvents.push_back (Simulator::Schedule (ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (event->GetTxVector ()),
553  &PhyEntity::EndReceivePayload, this, event));
554 }
555 
556 void
558 {
559  NS_LOG_FUNCTION (this << *event);
560  Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
562  const WifiTxVector& txVector = event->GetTxVector ();
563  uint16_t staId = GetStaId (ppdu);
564  Time endOfMpduDuration = NanoSeconds (0);
565  Time relativeStart = NanoSeconds (0);
566  Time psduDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
567  Time remainingAmpduDuration = psduDuration;
568  size_t nMpdus = psdu->GetNMpdus ();
569  MpduType mpduType = (nMpdus > 1) ? FIRST_MPDU_IN_AGGREGATE : (psdu->IsSingle () ? SINGLE_MPDU : NORMAL_MPDU);
570  uint32_t totalAmpduSize = 0;
571  double totalAmpduNumSymbols = 0.0;
572  auto mpdu = psdu->begin ();
573  for (size_t i = 0; i < nMpdus && mpdu != psdu->end (); ++mpdu)
574  {
575  uint32_t size = (mpduType == NORMAL_MPDU) ? psdu->GetSize () : psdu->GetAmpduSubframeSize (i);
576  Time mpduDuration = m_wifiPhy->GetPayloadDuration (size, txVector,
577  m_wifiPhy->GetPhyBand (), mpduType, true, totalAmpduSize,
578  totalAmpduNumSymbols, staId);
579 
580  remainingAmpduDuration -= mpduDuration;
581  if (i == (nMpdus - 1) && !remainingAmpduDuration.IsZero ()) //no more MPDUs coming
582  {
583  if (remainingAmpduDuration < NanoSeconds (txVector.GetGuardInterval ())) //enables to ignore padding
584  {
585  mpduDuration += remainingAmpduDuration; //apply a correction just in case rounding had induced slight shift
586  }
587  }
588 
589  endOfMpduDuration += mpduDuration;
590  NS_LOG_INFO ("Schedule end of MPDU #" << i << " in " << endOfMpduDuration.As (Time::NS) <<
591  " (relativeStart=" << relativeStart.As (Time::NS) << ", mpduDuration=" << mpduDuration.As (Time::NS) <<
592  ", remainingAmdpuDuration=" << remainingAmpduDuration.As (Time::NS) << ")");
593  m_endOfMpduEvents.push_back (Simulator::Schedule (endOfMpduDuration, &PhyEntity::EndOfMpdu, this, event, Create<WifiPsdu> (*mpdu, false), i, relativeStart, mpduDuration));
594 
595  //Prepare next iteration
596  ++i;
597  relativeStart += mpduDuration;
598  mpduType = (i == (nMpdus - 1)) ? LAST_MPDU_IN_AGGREGATE : MIDDLE_MPDU_IN_AGGREGATE;
599  }
600 }
601 
602 void
603 PhyEntity::EndOfMpdu (Ptr<Event> event, Ptr<const WifiPsdu> psdu, size_t mpduIndex, Time relativeStart, Time mpduDuration)
604 {
605  NS_LOG_FUNCTION (this << *event << mpduIndex << relativeStart << mpduDuration);
606  Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
607  WifiTxVector txVector = event->GetTxVector ();
608  uint16_t staId = GetStaId (ppdu);
609 
610  std::pair<bool, SignalNoiseDbm> rxInfo = GetReceptionStatus (psdu, event, staId, relativeStart, mpduDuration);
611  NS_LOG_DEBUG ("Extracted MPDU #" << mpduIndex << ": duration: " << mpduDuration.As (Time::NS) <<
612  ", correct reception: " << rxInfo.first << ", Signal/Noise: " << rxInfo.second.signal << "/" << rxInfo.second.noise << "dBm");
613 
614  auto signalNoiseIt = m_signalNoiseMap.find (std::make_pair (ppdu->GetUid (), staId));
615  NS_ASSERT (signalNoiseIt != m_signalNoiseMap.end ());
616  signalNoiseIt->second = rxInfo.second;
617 
618  RxSignalInfo rxSignalInfo;
619  rxSignalInfo.snr = rxInfo.second.signal / rxInfo.second.noise;
620  rxSignalInfo.rssi = rxInfo.second.signal;
621 
622  auto statusPerMpduIt = m_statusPerMpduMap.find (std::make_pair (ppdu->GetUid (), staId));
623  NS_ASSERT (statusPerMpduIt != m_statusPerMpduMap.end ());
624  statusPerMpduIt->second.push_back (rxInfo.first);
625 
626  if (rxInfo.first && GetAddressedPsduInPpdu (ppdu)->GetNMpdus () > 1)
627  {
628  //only done for correct MPDU that is part of an A-MPDU
629  m_state->ContinueRxNextMpdu (Copy (psdu), rxSignalInfo, txVector);
630  }
631 }
632 
633 void
635 {
636  Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
637  WifiTxVector txVector = event->GetTxVector ();
638  Time psduDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
639  NS_LOG_FUNCTION (this << *event << psduDuration);
640  NS_ASSERT (event->GetEndTime () == Simulator::Now ());
641  uint16_t staId = GetStaId (ppdu);
642  const auto & channelWidthAndBand = GetChannelWidthAndBand (event->GetTxVector (), staId);
643  double snr = m_wifiPhy->m_interference->CalculateSnr (event, channelWidthAndBand.first, txVector.GetNss (staId), channelWidthAndBand.second);
644 
646  m_wifiPhy->NotifyRxEnd (psdu);
647 
648  auto signalNoiseIt = m_signalNoiseMap.find (std::make_pair (ppdu->GetUid (), staId));
649  NS_ASSERT (signalNoiseIt != m_signalNoiseMap.end ());
650  auto statusPerMpduIt = m_statusPerMpduMap.find (std::make_pair (ppdu->GetUid (), staId));
651  NS_ASSERT (statusPerMpduIt != m_statusPerMpduMap.end ());
652 
653  if (std::count (statusPerMpduIt->second.begin (), statusPerMpduIt->second.end (), true))
654  {
655  //At least one MPDU has been successfully received
656  m_wifiPhy->NotifyMonitorSniffRx (psdu, m_wifiPhy->GetFrequency (), txVector, signalNoiseIt->second, statusPerMpduIt->second, staId);
657  RxSignalInfo rxSignalInfo;
658  rxSignalInfo.snr = snr;
659  rxSignalInfo.rssi = signalNoiseIt->second.signal; //same information for all MPDUs
660  m_state->SwitchFromRxEndOk (Copy (psdu), rxSignalInfo, txVector, staId, statusPerMpduIt->second);
661  m_wifiPhy->m_previouslyRxPpduUid = ppdu->GetUid (); //store UID only if reception is successful (because otherwise trigger won't be read by MAC layer)
662  }
663  else
664  {
665  m_state->SwitchFromRxEndError (Copy (psdu), snr);
666  }
667 
668  DoEndReceivePayload (ppdu);
670 }
671 
672 void
674 {
675  NS_LOG_FUNCTION (this << ppdu);
677  NotifyInterferenceRxEndAndClear (false); //don't reset WifiPhy
678 
681  m_endRxPayloadEvents.clear ();
682 }
683 
684 std::pair<bool, SignalNoiseDbm>
686  Time relativeMpduStart, Time mpduDuration)
687 {
688  NS_LOG_FUNCTION (this << *psdu << *event << staId << relativeMpduStart << mpduDuration);
689  const auto & channelWidthAndBand = GetChannelWidthAndBand (event->GetTxVector (), staId);
690  SnrPer snrPer = m_wifiPhy->m_interference->CalculatePayloadSnrPer (event, channelWidthAndBand.first, channelWidthAndBand.second, staId,
691  std::make_pair (relativeMpduStart, relativeMpduStart + mpduDuration));
692 
693  WifiMode mode = event->GetTxVector ().GetMode (staId);
694  NS_LOG_DEBUG ("rate=" << (mode.GetDataRate (event->GetTxVector (), staId)) <<
695  ", SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per << ", size=" << psdu->GetSize () <<
696  ", relativeStart = " << relativeMpduStart.As (Time::NS) << ", duration = " << mpduDuration.As (Time::NS));
697 
698  // There are two error checks: PER and receive error model check.
699  // PER check models is typical for Wi-Fi and is based on signal modulation;
700  // Receive error model is optional, if we have an error model and
701  // it indicates that the packet is corrupt, drop the packet.
702  SignalNoiseDbm signalNoise;
703  signalNoise.signal = WToDbm (event->GetRxPowerW (channelWidthAndBand.second));
704  signalNoise.noise = WToDbm (event->GetRxPowerW (channelWidthAndBand.second) / snrPer.snr);
705  if (GetRandomValue () > snrPer.per
707  {
708  NS_LOG_DEBUG ("Reception succeeded: " << psdu);
709  return std::make_pair (true, signalNoise);
710  }
711  else
712  {
713  NS_LOG_DEBUG ("Reception failed: " << psdu);
714  return std::make_pair (false, signalNoise);
715  }
716 }
717 
718 std::pair<uint16_t, WifiSpectrumBand>
719 PhyEntity::GetChannelWidthAndBand (const WifiTxVector& txVector, uint16_t /* staId */) const
720 {
721  uint16_t channelWidth = GetRxChannelWidth (txVector);
722  return std::make_pair (channelWidth, m_wifiPhy->GetPrimaryBand (channelWidth));
723 }
724 
725 const std::map <std::pair<uint64_t, WifiPreamble>, Ptr<Event> > &
727 {
729 }
730 
731 void
733 {
734  NS_LOG_FUNCTION (this << *event);
735  Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
736  m_wifiPhy->m_currentPreambleEvents.insert ({std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()), event});
737 }
738 
741 {
742  Ptr<Event> event = CreateInterferenceEvent (ppdu, ppdu->GetTxVector (), ppdu->GetTxDuration (), rxPowersW);
743 
744  //We store all incoming preamble events, and a decision is made at the end of the preamble detection window.
745  auto uidPreamblePair = std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ());
746  NS_ASSERT (m_wifiPhy->m_currentPreambleEvents.find (uidPreamblePair) == m_wifiPhy->m_currentPreambleEvents.end ());
747  m_wifiPhy->m_currentPreambleEvents.insert ({uidPreamblePair, event});
748  return event;
749 }
750 
752 PhyEntity::CreateInterferenceEvent (Ptr<const WifiPpdu> ppdu, const WifiTxVector& txVector, Time duration, RxPowerWattPerChannelBand& rxPower, bool isStartOfdmaRxing /* = false */)
753 {
754  return m_wifiPhy->m_interference->Add (ppdu, txVector, duration, rxPower, isStartOfdmaRxing);
755 }
756 
757 void
759 {
760  m_wifiPhy->m_interference->UpdateEvent (event, rxPower);
761 }
762 
763 void
765 {
766  m_wifiPhy->m_interference->NotifyRxEnd (Simulator::Now ());
767  m_signalNoiseMap.clear ();
768  m_statusPerMpduMap.clear ();
769  for (const auto & endOfMpduEvent : m_endOfMpduEvents)
770  {
771  NS_ASSERT (endOfMpduEvent.IsExpired ());
772  }
773  m_endOfMpduEvents.clear ();
774  if (reset)
775  {
776  m_wifiPhy->Reset ();
777  }
778 }
779 
782 {
783  NS_LOG_FUNCTION (this << *event);
784  NS_ASSERT (m_wifiPhy->m_currentPreambleEvents.size () == 1); //Synched on one after detection period
785  return PhyFieldRxStatus (true); //always consider that preamble has been correctly received if preamble detection was OK
786 }
787 
788 void
790 {
791  NS_LOG_FUNCTION (this << *event);
792  NS_LOG_DEBUG ("Sync to signal (power=" << WToDbm (GetRxPowerWForPpdu (event)) << "dBm)");
793  m_wifiPhy->m_interference->NotifyRxStart (); //We need to notify it now so that it starts recording events
795 }
796 
797 void
799 {
800  NS_LOG_FUNCTION (this << *event);
802  NS_ASSERT (m_wifiPhy->m_endPhyRxEvent.IsExpired ()); //since end of preamble reception is scheduled by this method upon success
803 
804  //calculate PER on the measurement channel for PHY headers
805  uint16_t measurementChannelWidth = GetMeasurementChannelWidth (event->GetPpdu ());
806  auto measurementBand = m_wifiPhy->GetPrimaryBand (measurementChannelWidth);
807  double maxRxPowerW = -1; //in case current event may not be sent on measurement channel (rxPowerW would be equal to 0)
808  Ptr<Event> maxEvent;
810  for (auto preambleEvent : m_wifiPhy->m_currentPreambleEvents)
811  {
812  double rxPowerW = preambleEvent.second->GetRxPowerW (measurementBand);
813  if (rxPowerW > maxRxPowerW)
814  {
815  maxRxPowerW = rxPowerW;
816  maxEvent = preambleEvent.second;
817  }
818  }
819 
820  NS_ASSERT (maxEvent != 0);
821  if (maxEvent != event)
822  {
823  NS_LOG_DEBUG ("Receiver got a stronger packet with UID " << maxEvent->GetPpdu ()->GetUid () << " during preamble detection: drop packet with UID " << event->GetPpdu ()->GetUid ());
825  auto it = m_wifiPhy->m_currentPreambleEvents.find (std::make_pair (event->GetPpdu ()->GetUid (), event->GetPpdu ()->GetPreamble ()));
827  //This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to the power at the start of the PPDU
828  m_wifiPhy->m_interference->NotifyRxEnd (maxEvent->GetStartTime ());
829  //Make sure InterferenceHelper keeps recording events
830  m_wifiPhy->m_interference->NotifyRxStart ();
831  return;
832  }
833 
834  m_wifiPhy->m_currentEvent = event;
835 
836  double snr = m_wifiPhy->m_interference->CalculateSnr (m_wifiPhy->m_currentEvent, measurementChannelWidth, 1, measurementBand);
837  NS_LOG_DEBUG ("SNR(dB)=" << RatioToDb (snr) << " at end of preamble detection period");
838 
839  if ((!m_wifiPhy->m_preambleDetectionModel && maxRxPowerW > 0.0)
840  || (m_wifiPhy->m_preambleDetectionModel && m_wifiPhy->m_preambleDetectionModel->IsPreambleDetected (m_wifiPhy->m_currentEvent->GetRxPowerW (measurementBand), snr, measurementChannelWidth)))
841  {
842  //A bit convoluted but it enables to sync all PHYs
843  for (auto & it : m_wifiPhy->m_phyEntities)
844  {
845  it.second->CancelRunningEndPreambleDetectionEvents (true);
846  }
847 
848  for (auto it = m_wifiPhy->m_currentPreambleEvents.begin (); it != m_wifiPhy->m_currentPreambleEvents.end (); )
849  {
850  if (it->second != m_wifiPhy->m_currentEvent)
851  {
852  NS_LOG_DEBUG ("Drop packet with UID " << it->first.first << " and preamble " << it->first.second << " arrived at time " << it->second->GetStartTime ());
853  WifiPhyRxfailureReason reason;
854  if (m_wifiPhy->m_currentEvent->GetPpdu ()->GetUid () > it->first.first)
855  {
857  //This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to the power at the start of the PPDU
858  m_wifiPhy->m_interference->NotifyRxEnd (m_wifiPhy->m_currentEvent->GetStartTime ());
859  }
860  else
861  {
862  reason = BUSY_DECODING_PREAMBLE;
863  }
864  m_wifiPhy->NotifyRxDrop (GetAddressedPsduInPpdu (it->second->GetPpdu ()), reason);
865  it = m_wifiPhy->m_currentPreambleEvents.erase (it);
866  }
867  else
868  {
869  ++it;
870  }
871  }
872 
873  //Make sure InterferenceHelper keeps recording events
874  m_wifiPhy->m_interference->NotifyRxStart ();
875 
878 
879  //Continue receiving preamble
880  Time durationTillEnd = GetDuration (WIFI_PPDU_FIELD_PREAMBLE, event->GetTxVector ()) - m_wifiPhy->GetPreambleDetectionDuration ();
881  m_state->SwitchMaybeToCcaBusy (durationTillEnd); //will be prolonged by next field
883  }
884  else
885  {
886  NS_LOG_DEBUG ("Drop packet because PHY preamble detection failed");
887  // Like CCA-SD, CCA-ED is governed by the 4 us CCA window to flag CCA-BUSY
888  // for any received signal greater than the CCA-ED threshold.
890  if (m_wifiPhy->m_currentPreambleEvents.empty ())
891  {
892  //Do not erase events if there are still pending preamble events to be processed
893  m_wifiPhy->m_interference->NotifyRxEnd (Simulator::Now ());
894  }
896  //Cancel preamble reception
898  }
899 }
900 
901 bool
903 {
904  WifiMode txMode = ppdu->GetTxVector ().GetMode ();
905  if (!IsModeSupported (txMode))
906  {
907  NS_LOG_DEBUG ("Drop packet because it was sent using an unsupported mode (" << txMode << ")");
908  return false;
909  }
910  return true;
911 }
912 
913 void
915 {
916  NS_LOG_FUNCTION (this);
917  for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
918  {
919  endPreambleDetectionEvent.Cancel ();
920  }
922  for (auto & endRxPayloadEvent : m_endRxPayloadEvents)
923  {
924  endRxPayloadEvent.Cancel ();
925  }
926  m_endRxPayloadEvents.clear ();
927  for (auto & endMpduEvent : m_endOfMpduEvents)
928  {
929  endMpduEvent.Cancel ();
930  }
931  m_endOfMpduEvents.clear ();
932 }
933 
934 bool
936 {
937  return m_endPreambleDetectionEvents.empty ();
938 }
939 
940 void
942 {
943  NS_LOG_FUNCTION (this << clear);
944  for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
945  {
946  if (endPreambleDetectionEvent.IsRunning ())
947  {
948  endPreambleDetectionEvent.Cancel ();
949  }
950  }
951  if (clear)
952  {
954  }
955 }
956 
957 void
959 {
960  NS_LOG_FUNCTION (this << reason);
961  DoAbortCurrentReception (reason);
963 }
964 
965 void
967 {
968  NS_LOG_FUNCTION (this << reason);
969  if (m_wifiPhy->m_currentEvent) //Otherwise abort has already been called just before
970  {
971  for (auto & endMpduEvent : m_endOfMpduEvents)
972  {
973  endMpduEvent.Cancel ();
974  }
975  m_endOfMpduEvents.clear ();
976  }
977 }
978 
979 void
981 {
982  NS_LOG_FUNCTION (this << *event);
983  DoResetReceive (event);
984  NS_ASSERT (m_endRxPayloadEvents.size () == 1 && m_endRxPayloadEvents.front ().IsExpired ());
985  m_endRxPayloadEvents.clear ();
986  m_wifiPhy->ResetReceive (event);
987 }
988 
989 void
991 {
992  NS_LOG_FUNCTION (this << *event);
993  NS_ASSERT (event->GetEndTime () == Simulator::Now ());
994 }
995 
996 double
998 {
999  return m_wifiPhy->m_random->GetValue ();
1000 }
1001 
1002 double
1004 {
1005  return event->GetRxPowerW (m_wifiPhy->GetPrimaryBand (GetMeasurementChannelWidth (event->GetPpdu ())));
1006 }
1007 
1010 {
1011  return m_wifiPhy->m_currentEvent;
1012 }
1013 
1014 uint16_t
1016 {
1017  return GetRxChannelWidth (ppdu->GetTxVector ());
1018 }
1019 
1020 uint16_t
1022 {
1023  return std::min (m_wifiPhy->GetChannelWidth (), txVector.GetChannelWidth ());
1024 }
1025 
1026 uint64_t
1028 {
1029  NS_LOG_FUNCTION (this);
1030  return m_globalPpduUid++;
1031 }
1032 
1033 uint16_t
1035 {
1036  NS_LOG_FUNCTION (this << txVector);
1037 
1039 }
1040 
1041 void
1042 PhyEntity::NotifyPayloadBegin (const WifiTxVector& txVector, const Time& payloadDuration)
1043 {
1044  m_wifiPhy->m_phyRxPayloadBeginTrace (txVector, payloadDuration);
1045 }
1046 
1047 void
1049 {
1050  NS_LOG_FUNCTION (this << ppdu);
1051  Transmit (ppdu->GetTxDuration (), ppdu, "transmission");
1052 }
1053 
1054 void
1055 PhyEntity::Transmit (Time txDuration, Ptr<WifiPpdu> ppdu, std::string type)
1056 {
1057  NS_LOG_FUNCTION (this << txDuration << ppdu << type);
1058  double txPowerWatts = DbmToW (m_wifiPhy->GetTxPowerForTransmission (ppdu) + m_wifiPhy->GetTxGain ());
1059  NS_LOG_DEBUG ("Start " << type << ": signal power before antenna gain=" << WToDbm (txPowerWatts) << "dBm");
1060  Ptr<SpectrumValue> txPowerSpectrum = GetTxPowerSpectralDensity (txPowerWatts, ppdu);
1061  Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters> ();
1062  txParams->duration = txDuration;
1063  txParams->psd = txPowerSpectrum;
1064  txParams->ppdu = ppdu;
1065  txParams->txCenterFreq = GetCenterFrequencyForChannelWidth (ppdu->GetTxVector ());
1066  NS_LOG_DEBUG ("Starting " << type << " with power " << WToDbm (txPowerWatts) << " dBm on channel " << +m_wifiPhy->GetChannelNumber () << " for " << txParams->duration.As (Time::MS));
1067  NS_LOG_DEBUG ("Starting " << type << " with integrated spectrum power " << WToDbm (Integral (*txPowerSpectrum)) << " dBm; spectrum model Uid: " << txPowerSpectrum->GetSpectrumModel ()->GetUid ());
1068  auto spectrumWifiPhy = DynamicCast<SpectrumWifiPhy> (m_wifiPhy);
1069  NS_ASSERT (spectrumWifiPhy);
1070  spectrumWifiPhy->Transmit (txParams);
1071 }
1072 
1073 uint16_t
1074 PhyEntity::GetGuardBandwidth (uint16_t currentChannelWidth) const
1075 {
1076  return m_wifiPhy->GetGuardBandwidth (currentChannelWidth);
1077 }
1078 
1079 std::tuple<double, double, double>
1081 {
1083 }
1084 
1085 Time
1087 {
1088  NS_ASSERT (psduMap.size () == 1);
1089  const auto & it = psduMap.begin ();
1090  return WifiPhy::CalculateTxDuration (it->second->GetSize (), txVector, band, it->first);
1091 }
1092 
1093 } //namespace ns3
#define min(a, b)
Definition: 80211b.c:42
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:65
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
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:1042
const std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents(void) const
Get the map of current preamble events (stored in WifiPhy).
Definition: phy-entity.cc:726
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:781
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper of the WifiPhy (to make it reachable for child classes)
Definition: phy-entity.h:792
void EndPreambleDetectionPeriod(Ptr< Event > event)
End the preamble detection period.
Definition: phy-entity.cc:798
virtual Ptr< WifiPpdu > BuildPpdu(const WifiConstPsduMap &psdus, const WifiTxVector &txVector, Time ppduDuration)
Build amendment-specific PPDU.
Definition: phy-entity.cc:230
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:178
virtual uint64_t ObtainNextUid(const WifiTxVector &txVector)
Obtain the next UID for the PPDU to transmit.
Definition: phy-entity.cc:1027
virtual void CancelAllEvents(void)
Cancel and clear all running events.
Definition: phy-entity.cc:914
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:752
virtual Ptr< SpectrumValue > GetTxPowerSpectralDensity(double txPowerW, Ptr< const WifiPpdu > ppdu) const =0
virtual void StartReceivePreamble(Ptr< WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW, Time rxDuration)
Start receiving the PHY preamble of a PPDU (i.e.
Definition: phy-entity.cc:364
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:807
Ptr< WifiPhy > m_wifiPhy
Pointer to the owning WifiPhy.
Definition: phy-entity.h:791
std::vector< EventId > m_endOfMpduEvents
the end of MPDU events (only used for A-MPDUs)
Definition: phy-entity.h:797
bool NoEndPreambleDetectionEvents(void) const
Definition: phy-entity.cc:935
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:719
std::list< WifiMode >::const_iterator end(void) const
Return a const iterator to past-the-last WifiMode.
Definition: phy-entity.cc:136
virtual ~PhyEntity()
Destructor for PHY entity.
Definition: phy-entity.cc:75
double GetRandomValue(void) const
Obtain a random value from the WifiPhy's generator.
Definition: phy-entity.cc:997
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:334
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition: phy-entity.cc:83
virtual bool HandlesMcsModes(void) const
Check if the WifiModes handled by this PHY are MCSs.
Definition: phy-entity.cc:124
std::list< WifiMode >::const_iterator begin(void) const
Return a const iterator to the first WifiMode.
Definition: phy-entity.cc:130
std::tuple< double, double, double > GetTxMaskRejectionParams(void) const
Definition: phy-entity.cc:1080
virtual void DoAbortCurrentReception(WifiPhyRxfailureReason reason)
Perform amendment-specific actions before aborting the current reception.
Definition: phy-entity.cc:966
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Abort the current reception.
Definition: phy-entity.cc:958
void EndReceivePayload(Ptr< Event > event)
The last symbol of the PPDU has arrived.
Definition: phy-entity.cc:634
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:809
PhyHeaderSections GetPhyHeaderSections(const WifiTxVector &txVector, Time ppduStart) const
Return a map of PHY header chunk information per PPDU field.
Definition: phy-entity.cc:211
virtual bool IsMcsSupported(uint8_t index) const
Check if the WifiMode corresponding to the given MCS index is supported.
Definition: phy-entity.cc:117
void StartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
Definition: phy-entity.cc:528
std::vector< EventId > m_endRxPayloadEvents
the end of receive events (only one unless UL MU reception)
Definition: phy-entity.h:799
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:990
void EndReceiveField(WifiPpduField field, Ptr< Event > event)
End receiving a given field.
Definition: phy-entity.cc:281
virtual Ptr< Event > DoGetEvent(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW)
Get the event corresponding to the incoming PPDU.
Definition: phy-entity.cc:740
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:142
WifiPpduField GetNextField(WifiPpduField currentField, WifiPreamble preamble) const
Return the field following the provided one.
Definition: phy-entity.cc:149
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Definition: phy-entity.h:301
double GetRxPowerWForPpdu(Ptr< Event > event) const
Obtain the received power (W) for a given band.
Definition: phy-entity.cc:1003
virtual void DoStartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
Definition: phy-entity.cc:543
Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector) const
Definition: phy-entity.cc:188
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:764
void StartPreambleDetectionPeriod(Ptr< Event > event)
Start the preamble detection period.
Definition: phy-entity.cc:789
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:238
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:806
virtual uint16_t GetRxChannelWidth(const WifiTxVector &txVector) const
Return the channel width used in the reception spectrum model.
Definition: phy-entity.cc:1021
void CancelRunningEndPreambleDetectionEvents(bool clear=false)
Cancel and eventually clear all end preamble detection events.
Definition: phy-entity.cc:941
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:327
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:522
virtual void StartTx(Ptr< WifiPpdu > ppdu)
This function is called by SpectrumWifiPhy to send the PPDU while performing amendment-specific actio...
Definition: phy-entity.cc:1048
virtual Time CalculateTxDuration(WifiConstPsduMap psduMap, const WifiTxVector &txVector, WifiPhyBand band) const
Definition: phy-entity.cc:1086
void StartReceiveField(WifiPpduField field, Ptr< Event > event)
Start receiving a given field.
Definition: phy-entity.cc:260
void Transmit(Time txDuration, Ptr< WifiPpdu > ppdu, std::string type)
This function prepares most of the WifiSpectrumSignalParameters parameters and invokes SpectrumWifiPh...
Definition: phy-entity.cc:1055
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const
Definition: phy-entity.cc:1074
virtual bool IsModeSupported(WifiMode mode) const
Check if the WifiMode is supported.
Definition: phy-entity.cc:91
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:980
std::list< WifiMode > m_modeList
the list of supported modes
Definition: phy-entity.h:794
std::vector< EventId > m_endPreambleDetectionEvents
the end of preamble detection events
Definition: phy-entity.h:796
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:205
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:252
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:501
void DropPreambleEvent(Ptr< const WifiPpdu > ppdu, WifiPhyRxfailureReason reason, Time endRx, uint16_t measurementChannelWidth)
Drop the PPDU and the corresponding preamble detection event, but keep CCA busy state after the compl...
Definition: phy-entity.cc:484
Ptr< const Event > GetCurrentEvent(void) const
Get the pointer to the current event (stored in WifiPhy).
Definition: phy-entity.cc:1009
virtual WifiMode GetMcs(uint8_t index) const
Get the WifiMode corresponding to the given MCS index.
Definition: phy-entity.cc:110
void AddPreambleEvent(Ptr< Event > event)
Add an entry to the map of current preamble events (stored in WifiPhy).
Definition: phy-entity.cc:732
virtual void DoEndReceivePayload(Ptr< const WifiPpdu > ppdu)
Perform amendment-specific actions at the end of the reception of the payload.
Definition: phy-entity.cc:673
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:1034
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:199
virtual bool IsConfigSupported(Ptr< const WifiPpdu > ppdu) const
Checks if the signaled configuration (excluding bandwidth) is supported by the PHY.
Definition: phy-entity.cc:902
virtual uint16_t GetMeasurementChannelWidth(const Ptr< const WifiPpdu > ppdu) const
Return the channel width used to measure the RSSI.
Definition: phy-entity.cc:1015
PhyRxFailureAction
Action to perform in case of RX failure.
Definition: phy-entity.h:101
@ DROP
drop PPDU and set CCA_BUSY
Definition: phy-entity.h:102
@ IGNORE
ignore the reception
Definition: phy-entity.h:104
@ ABORT
abort reception of PPDU
Definition: phy-entity.h:103
void UpdateInterferenceEvent(Ptr< Event > event, const RxPowerWattPerChannelBand &rxPower)
Update an event in WifiPhy's InterferenceHelper class.
Definition: phy-entity.cc:758
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:685
virtual const PpduFormats & GetPpduFormats(void) const =0
Return the PPDU formats of the PHY.
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:603
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:352
virtual uint8_t GetNumModes(void) const
Definition: phy-entity.cc:104
void ScheduleEndOfMpdus(Ptr< Event > event)
Schedule end of MPDUs events.
Definition: phy-entity.cc:557
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
SpectrumModelUid_t GetUid() const
Ptr< const SpectrumModel > GetSpectrumModel() const
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
@ MS
millisecond
Definition: nstime.h:115
@ NS
nanosecond
Definition: nstime.h:117
bool IsZero(void) const
Exactly equivalent to t == 0.
Definition: nstime.h:300
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:418
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
represent a single transmission mode
Definition: wifi-mode.h:48
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:114
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper.
Definition: wifi-phy.h:1145
Ptr< UniformRandomVariable > m_random
Provides uniform random variables.
Definition: wifi-phy.h:1144
uint8_t GetChannelNumber(void) const
Return current channel number.
Definition: wifi-phy.cc:912
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:1303
const WifiPhyOperatingChannel & GetOperatingChannel(void) const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:900
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:1154
bool IsStateRx(void) const
Definition: wifi-phy.cc:1821
WifiPhyBand GetPhyBand(void) const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:887
EventId m_endPhyRxEvent
the end of PHY receive event
Definition: wifi-phy.h:1150
void NotifyRxDrop(Ptr< const WifiPsdu > psdu, WifiPhyRxfailureReason reason)
Public method used to fire a PhyRxDrop trace.
Definition: wifi-phy.cc:1420
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Due to newly arrived signal, the current reception cannot be continued and has to be aborted.
Definition: wifi-phy.cc:1885
Ptr< FrameCaptureModel > m_frameCaptureModel
Frame capture model.
Definition: wifi-phy.h:1390
void NotifyRxBegin(Ptr< const WifiPsdu > psdu, const RxPowerWattPerChannelBand &rxPowersW)
Public method used to fire a PhyRxBegin trace.
Definition: wifi-phy.cc:1396
uint16_t GetMeasurementChannelWidth(const Ptr< const WifiPpdu > ppdu) const
Return the channel width used to measure the RSSI.
Definition: wifi-phy.cc:1980
void ResetReceive(Ptr< Event > event)
Reset PHY at the end of the packet under reception after it has failed the PHY header.
Definition: wifi-phy.cc:1661
virtual uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const =0
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1327
void Reset(void)
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1611
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1175
Ptr< ErrorModel > m_postReceptionErrorModel
Error model for receive packet events.
Definition: wifi-phy.h:1393
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1153
virtual std::tuple< double, double, double > GetTxMaskRejectionParams(void) const =0
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1156
Ptr< PreambleDetectionModel > m_preambleDetectionModel
Preamble detection model.
Definition: wifi-phy.h:1391
void SwitchMaybeToCcaBusy(uint16_t channelWidth)
Check if PHY state should move to CCA busy state based on current state of interference tracker.
Definition: wifi-phy.cc:1869
void NotifyRxEnd(Ptr< const WifiPsdu > psdu)
Public method used to fire a PhyRxEnd trace.
Definition: wifi-phy.cc:1408
WifiSpectrumBand GetPrimaryBand(uint16_t bandWidth)
If the operating channel width is a multiple of 20 MHz, return the start band index and the stop band...
Definition: wifi-phy.cc:2001
double GetTxGain(void) const
Return the transmission gain (dB).
Definition: wifi-phy.cc:503
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1142
double GetTxPowerForTransmission(Ptr< const WifiPpdu > ppdu) const
Compute the transmit power for the next transmission.
Definition: wifi-phy.cc:1940
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:1432
TracedCallback< WifiTxVector, Time > m_phyRxPayloadBeginTrace
The trace source fired when the reception of the PHY payload (PSDU) begins.
Definition: wifi-phy.h:1298
static Time GetPreambleDetectionDuration(void)
Definition: wifi-phy.cc:1291
Time m_timeLastPreambleDetected
Record the time the last preamble was detected.
Definition: wifi-phy.h:1394
Time GetLastRxEndTime(void) const
Return the end time of the last received packet.
Definition: wifi-phy.cc:1863
uint16_t GetChannelWidth(void) const
Definition: wifi-phy.cc:918
uint16_t GetFrequency(void) const
Definition: wifi-phy.cc:906
uint16_t GetPrimaryChannelCenterFrequency(uint16_t primaryChannelWidth) const
Get the center frequency of the primary channel of the given width.
uint32_t GetSize(void) const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:260
std::vector< Ptr< WifiMacQueueItem > >::const_iterator begin(void) const
Return a const iterator to the first MPDU.
Definition: wifi-psdu.cc:325
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:319
std::vector< Ptr< WifiMacQueueItem > >::const_iterator end(void) const
Return a const iterator to past-the-last MPDU.
Definition: wifi-psdu.cc:337
std::size_t GetAmpduSubframeSize(std::size_t i) const
Return the size of the i-th A-MPDU subframe.
Definition: wifi-psdu.cc:306
bool IsSingle(void) const
Return true if the PSDU is an S-MPDU.
Definition: wifi-psdu.cc:75
Ptr< const Packet > GetPacket(void) const
Get the PSDU as a single packet.
Definition: wifi-psdu.cc:87
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiPreamble GetPreambleType(void) 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(void) const
uint16_t GetGuardInterval(void) 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:67
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#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:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#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:281
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1268
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
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_PPDU_FIELD_SIG_B
SIG-B 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:49
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:43
double Integral(const SpectrumValue &arg)
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:37
std::map< WifiSpectrumBand, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Definition: phy-entity.h:75
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139
Ptr< T > Copy(Ptr< T > object)
Return a deep copy of a Ptr.
Definition: ptr.h:555
def start()
Definition: core.py:1853
Declaration of:
Status of the reception of the PPDU field.
Definition: phy-entity.h:111
WifiPhyRxfailureReason reason
failure reason
Definition: phy-entity.h:114
PhyRxFailureAction actionIfFailure
action to perform in case of failure
Definition: phy-entity.h:115
bool isSuccess
outcome (true if success) of the reception
Definition: phy-entity.h:113
A struct for both SNR and PER.
Definition: phy-entity.h:137
double snr
SNR in linear scale.
Definition: phy-entity.h:138
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:67
double rssi
RSSI in dBm.
Definition: phy-entity.h:69
double snr
SNR in linear scale.
Definition: phy-entity.h:68
SignalNoiseDbm structure.
Definition: phy-entity.h:53
double noise
noise power in dBm
Definition: phy-entity.h:55
double signal
signal strength in dBm
Definition: phy-entity.h:54
#define SU_STA_ID
Definition: wifi-mode.h:32
@ 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.