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