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  }
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
#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
void UpdateEvent(Ptr< Event > event, RxPowerWattPerChannelBand rxPower)
Update event to scale its received power (W) per band.
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.
void NotifyRxEnd(Time endTime)
Notify that RX has ended.
void NotifyRxStart()
Notify that RX has started.
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).
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.
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...
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
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
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
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper of the WifiPhy (to make it reachable for child classes)
Definition: phy-entity.h:784
virtual Ptr< Event > DoGetEvent(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand rxPowersW)
Get the event corresponding to the incoming PPDU.
Definition: phy-entity.cc:739
void EndPreambleDetectionPeriod(Ptr< Event > event)
End the preamble detection period.
Definition: phy-entity.cc:797
virtual Ptr< WifiPpdu > BuildPpdu(const WifiConstPsduMap &psdus, const WifiTxVector &txVector, Time ppduDuration)
Build amendment-specific PPDU.
Definition: phy-entity.cc:228
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
virtual void CancelAllEvents(void)
Cancel and clear all running events.
Definition: phy-entity.cc:913
virtual Ptr< SpectrumValue > GetTxPowerSpectralDensity(double txPowerW, Ptr< const WifiPpdu > ppdu) const =0
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
Ptr< WifiPhy > m_wifiPhy
Pointer to the owning WifiPhy.
Definition: phy-entity.h:783
std::vector< EventId > m_endOfMpduEvents
the end of MPDU events (only used for A-MPDUs)
Definition: phy-entity.h:789
bool NoEndPreambleDetectionEvents(void) const
Definition: phy-entity.cc:929
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
std::list< WifiMode >::const_iterator end(void) const
Return a const iterator to past-the-last WifiMode.
Definition: phy-entity.cc:135
void UpdateInterferenceEvent(Ptr< Event > event, RxPowerWattPerChannelBand rxPower)
Update an event in WifiPhy's InterferenceHelper class.
Definition: phy-entity.cc:757
virtual ~PhyEntity()
Destructor for PHY entity.
Definition: phy-entity.cc:74
double GetRandomValue(void) const
Obtain a random value from the WifiPhy's generator.
Definition: phy-entity.cc:991
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
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition: phy-entity.cc:82
virtual bool HandlesMcsModes(void) const
Check if the WifiModes handled by this PHY are MCSs.
Definition: phy-entity.cc:123
std::list< WifiMode >::const_iterator begin(void) const
Return a const iterator to the first WifiMode.
Definition: phy-entity.cc:129
std::tuple< double, double, double > GetTxMaskRejectionParams(void) const
Definition: phy-entity.cc:1067
virtual void DoAbortCurrentReception(WifiPhyRxfailureReason reason)
Perform amendment-specific actions before aborting the current reception.
Definition: phy-entity.cc:960
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Abort the current reception.
Definition: phy-entity.cc:952
void EndReceivePayload(Ptr< Event > event)
The last symbol of the PPDU has arrived.
Definition: phy-entity.cc:633
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:801
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
PhyHeaderSections GetPhyHeaderSections(const WifiTxVector &txVector, Time ppduStart) const
Return a map of PHY header chunk information per PPDU field.
Definition: phy-entity.cc:209
virtual bool IsMcsSupported(uint8_t index) const
Check if the WifiMode corresponding to the given MCS index is supported.
Definition: phy-entity.cc:116
void StartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
Definition: phy-entity.cc:525
std::vector< EventId > m_endRxPayloadEvents
the end of receive events (only one unless UL MU reception)
Definition: phy-entity.h:791
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 EndReceiveField(WifiPpduField field, Ptr< Event > event)
End receiving a given field.
Definition: phy-entity.cc:279
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
WifiPpduField GetNextField(WifiPpduField currentField, WifiPreamble preamble) const
Return the field following the provided one.
Definition: phy-entity.cc:148
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:997
virtual void DoStartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
Definition: phy-entity.cc:540
Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector) const
Definition: phy-entity.cc:186
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:763
void StartPreambleDetectionPeriod(Ptr< Event > event)
Start the preamble detection period.
Definition: phy-entity.cc:788
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
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
virtual uint16_t GetRxChannelWidth(const WifiTxVector &txVector) const
Return the channel width used in the reception spectrum model.
Definition: phy-entity.cc:1015
void CancelRunningEndPreambleDetectionEvents(bool clear=false)
Cancel and eventually clear all end preamble detection events.
Definition: phy-entity.cc:935
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
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
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
virtual Time CalculateTxDuration(WifiConstPsduMap psduMap, const WifiTxVector &txVector, WifiPhyBand band) const
Definition: phy-entity.cc:1073
void StartReceiveField(WifiPpduField field, Ptr< Event > event)
Start receiving a given field.
Definition: phy-entity.cc:258
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
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const
Definition: phy-entity.cc:1061
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:751
virtual bool IsModeSupported(WifiMode mode) const
Check if the WifiMode is supported.
Definition: phy-entity.cc:90
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::list< WifiMode > m_modeList
the list of supported modes
Definition: phy-entity.h:786
std::vector< EventId > m_endPreambleDetectionEvents
the end of preamble detection events
Definition: phy-entity.h:788
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
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:250
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
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
Ptr< const Event > GetCurrentEvent(void) const
Get the pointer to the current event (stored in WifiPhy).
Definition: phy-entity.cc:1003
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
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
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
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
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
virtual uint16_t GetMeasurementChannelWidth(const Ptr< const WifiPpdu > ppdu) const
Return the channel width used to measure the RSSI.
Definition: phy-entity.cc:1009
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
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
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:600
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
virtual uint8_t GetNumModes(void) const
Definition: phy-entity.cc:103
void ScheduleEndOfMpdus(Ptr< Event > event)
Schedule end of MPDUs events.
Definition: phy-entity.cc:554
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
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:104
@ MS
millisecond
Definition: nstime.h:116
@ NS
nanosecond
Definition: nstime.h:118
bool IsZero(void) const
Exactly equivalent to t == 0.
Definition: nstime.h:301
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
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:100
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper.
Definition: wifi-phy.h:1164
Ptr< UniformRandomVariable > m_random
Provides uniform random variables.
Definition: wifi-phy.h:1163
uint8_t GetChannelNumber(void) const
Return current channel number.
Definition: wifi-phy.cc:1199
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
void MaybeCcaBusyDuration(uint16_t channelWidth)
Eventually switch to CCA busy.
Definition: wifi-phy.cc:1914
const WifiPhyOperatingChannel & GetOperatingChannel(void) const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1137
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
bool IsStateRx(void) const
Definition: wifi-phy.cc:2107
WifiPhyBand GetPhyBand(void) const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1124
EventId m_endPhyRxEvent
the end of PHY receive event
Definition: wifi-phy.h:1169
void NotifyRxDrop(Ptr< const WifiPsdu > psdu, WifiPhyRxfailureReason reason)
Public method used to fire a PhyRxDrop trace.
Definition: wifi-phy.cc:1694
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
Ptr< FrameCaptureModel > m_frameCaptureModel
Frame capture model.
Definition: wifi-phy.h:1416
uint16_t GetMeasurementChannelWidth(const Ptr< const WifiPpdu > ppdu) const
Return the channel width used to measure the RSSI.
Definition: wifi-phy.cc:2266
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
virtual uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const =0
InterferenceHelper m_interference
the class handling interference computations
Definition: wifi-phy.h:1162
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1610
void Reset(void)
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1882
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1194
Ptr< ErrorModel > m_postReceptionErrorModel
Error model for receive packet events.
Definition: wifi-phy.h:1419
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1172
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:1175
Ptr< PreambleDetectionModel > m_preambleDetectionModel
Preamble detection model.
Definition: wifi-phy.h:1417
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
void NotifyRxEnd(Ptr< const WifiPsdu > psdu)
Public method used to fire a PhyRxEnd trace.
Definition: wifi-phy.cc:1682
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
void NotifyRxBegin(Ptr< const WifiPsdu > psdu, RxPowerWattPerChannelBand rxPowersW)
Public method used to fire a PhyRxBegin trace.
Definition: wifi-phy.cc:1670
double GetTxGain(void) const
Return the transmission gain (dB).
Definition: wifi-phy.cc:745
double GetTxPowerForTransmission(Ptr< const WifiPpdu > ppdu) const
Compute the transmit power for the next transmission.
Definition: wifi-phy.cc:2226
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
TracedCallback< WifiTxVector, Time > m_phyRxPayloadBeginTrace
The trace source fired when the reception of the PHY payload (PSDU) begins.
Definition: wifi-phy.h:1323
static Time GetPreambleDetectionDuration(void)
Definition: wifi-phy.cc:1574
Time m_timeLastPreambleDetected
Record the time the last preamble was detected.
Definition: wifi-phy.h:1420
Time GetLastRxEndTime(void) const
Return the end time of the last received packet.
Definition: wifi-phy.cc:2149
uint16_t GetChannelWidth(void) const
Definition: wifi-phy.cc:1233
uint16_t GetFrequency(void) const
Definition: wifi-phy.cc:1168
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:1305
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1313
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
@ FRAME_CAPTURE_PACKET_SWITCH
@ 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:53
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:47
double Integral(const SpectrumValue &arg)
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:41
std::map< WifiSpectrumBand, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Definition: phy-entity.h:75
Ptr< T > Copy(Ptr< T > object)
Return a deep copy of a Ptr.
Definition: ptr.h:536
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:137
def start()
Definition: core.py:1855
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.