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