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