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({{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] = {{start, start + duration}, GetSigMode(field, txVector)};
233 // Move to next field
234 start += duration;
235 field = GetNextField(field, txVector.GetPreambleType());
236 }
237 return map;
238}
239
241PhyEntity::BuildPpdu(const WifiConstPsduMap& psdus, const WifiTxVector& txVector, Time ppduDuration)
242{
243 NS_LOG_FUNCTION(this << psdus << txVector << ppduDuration);
244 NS_FATAL_ERROR("This method is unsupported for the base PhyEntity class. Use the overloaded "
245 "version in the amendment-specific subclasses instead!");
246 return Create<WifiPpdu>(psdus.begin()->second,
247 txVector,
248 m_wifiPhy->GetOperatingChannel()); // should be overloaded
249}
250
251Time
253{
254 if (field ==
255 WIFI_PPDU_FIELD_DATA) // this field is not in the map returned by GetPhyHeaderSections
256 {
258 }
259 const auto& sections = GetPhyHeaderSections(txVector, NanoSeconds(0));
260 auto it = sections.find(field);
261 NS_ASSERT(it != sections.end());
262 const auto& startStopTimes = it->second.first;
263 return startStopTimes
264 .first; // return the start time of field relatively to the beginning of the PPDU
265}
266
269{
270 uint16_t measurementChannelWidth = GetMeasurementChannelWidth(event->GetPpdu());
271 return m_wifiPhy->m_interference->CalculatePhyHeaderSnrPer(
272 event,
273 measurementChannelWidth,
274 GetPrimaryBand(measurementChannelWidth),
275 field);
276}
277
278void
280{
281 NS_LOG_FUNCTION(this << field << *event);
282 NS_ASSERT(m_wifiPhy); // no sense if no owner WifiPhy instance
285 "Use the StartReceivePreamble method for preamble reception");
286 // Handle special cases of data reception
287 if (field == WIFI_PPDU_FIELD_DATA)
288 {
289 StartReceivePayload(event);
290 return;
291 }
292
293 bool supported = DoStartReceiveField(field, event);
294 NS_ABORT_MSG_IF(!supported,
295 "Unknown field "
296 << field << " for this PHY entity"); // TODO see what to do if not supported
297 Time duration = GetDuration(field, event->GetPpdu()->GetTxVector());
299 Simulator::Schedule(duration, &PhyEntity::EndReceiveField, this, field, event);
301 event->GetPpdu(),
302 duration); // keep in CCA busy state up to reception of Data (will then switch to RX)
303}
304
305void
307{
308 NS_LOG_FUNCTION(this << field << *event);
309 NS_ASSERT(m_wifiPhy); // no sense if no owner WifiPhy instance
311 PhyFieldRxStatus status = DoEndReceiveField(field, event);
312 const auto& txVector = event->GetPpdu()->GetTxVector();
313 if (status.isSuccess) // move to next field if reception succeeded
314 {
315 StartReceiveField(GetNextField(field, txVector.GetPreambleType()), event);
316 }
317 else
318 {
319 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
320 switch (status.actionIfFailure)
321 {
322 case ABORT:
323 // Abort reception, but consider medium as busy
325 if (event->GetEndTime() > (Simulator::Now() + m_state->GetDelayUntilIdle()))
326 {
328 }
329 break;
330 case DROP:
331 // Notify drop, keep in CCA busy, and perform same processing as IGNORE case
332 if (status.reason == FILTERED)
333 {
334 // PHY-RXSTART is immediately followed by PHY-RXEND (Filtered)
336 txVector,
337 NanoSeconds(0)); // this callback (equivalent to PHY-RXSTART primitive) is also
338 // triggered for filtered PPDUs
339 }
342 // no break
343 case IGNORE:
344 // Keep in Rx state and reset at end
345 m_endRxPayloadEvents.push_back(
348 this,
349 event));
350 break;
351 default:
352 NS_FATAL_ERROR("Unknown action in case of failure");
353 }
354 }
355}
356
357Time
359{
360 const auto& txVector = ppdu->GetTxVector();
361 return ppdu->GetTxDuration() -
362 (GetDurationUpToField(field, txVector) + GetDuration(field, txVector));
363}
364
365bool
367{
368 NS_LOG_FUNCTION(this << field << *event);
370 field != WIFI_PPDU_FIELD_DATA); // handled apart for the time being
371 auto ppduFormats = GetPpduFormats();
372 auto itFormat = ppduFormats.find(event->GetPpdu()->GetPreamble());
373 if (itFormat != ppduFormats.end())
374 {
375 auto itField = std::find(itFormat->second.begin(), itFormat->second.end(), field);
376 if (itField != itFormat->second.end())
377 {
378 return true; // supported field so we can start receiving
379 }
380 }
381 return false; // unsupported otherwise
382}
383
386{
387 NS_LOG_FUNCTION(this << field << *event);
388 NS_ASSERT(field != WIFI_PPDU_FIELD_DATA); // handled apart for the time being
389 if (field == WIFI_PPDU_FIELD_PREAMBLE)
390 {
391 return DoEndReceivePreamble(event);
392 }
393 return PhyFieldRxStatus(false); // failed reception by default
394}
395
396void
398 RxPowerWattPerChannelBand& rxPowersW,
399 Time rxDuration)
400{
401 // The total RX power corresponds to the maximum over all the bands
402 auto it =
403 std::max_element(rxPowersW.begin(), rxPowersW.end(), [](const auto& p1, const auto& p2) {
404 return p1.second < p2.second;
405 });
406 NS_LOG_FUNCTION(this << ppdu << it->second);
407
408 auto event = DoGetEvent(ppdu, rxPowersW);
409 if (!event)
410 {
411 // PPDU should be simply considered as interference (once it has been accounted for in
412 // InterferenceHelper)
413 return;
414 }
415
416 Time endRx = Simulator::Now() + rxDuration;
417 if (ppdu->IsTruncatedTx())
418 {
419 NS_LOG_DEBUG("Packet reception stopped because transmitter has been switched off");
420 if (endRx > (Simulator::Now() + m_state->GetDelayUntilIdle()))
421 {
423 }
425 return;
426 }
427
428 switch (m_state->GetState())
429 {
430 case WifiPhyState::SWITCHING:
431 NS_LOG_DEBUG("Drop packet because of channel switching");
432 /*
433 * Packets received on the upcoming channel are added to the event list
434 * during the switching state. This way the medium can be correctly sensed
435 * when the device listens to the channel for the first time after the
436 * switching e.g. after channel switching, the channel may be sensed as
437 * busy due to other devices' transmissions started before the end of
438 * the switching.
439 */
441 break;
442 case WifiPhyState::RX:
444 m_wifiPhy->m_frameCaptureModel->IsInCaptureWindow(
446 m_wifiPhy->m_frameCaptureModel->CaptureNewFrame(m_wifiPhy->m_currentEvent, event))
447 {
449 NS_LOG_DEBUG("Switch to new packet");
451 }
452 else
453 {
454 NS_LOG_DEBUG("Drop packet because already in Rx");
455 DropPreambleEvent(ppdu, RXING, endRx);
457 {
458 /*
459 * We are here because the non-legacy PHY header has not been successfully received.
460 * The PHY is kept in RX state for the duration of the PPDU, but EndReceive function
461 * is not called when the reception of the PPDU is finished, which is responsible to
462 * clear m_currentPreambleEvents. As a result, m_currentPreambleEvents should be
463 * cleared here.
464 */
466 }
467 }
468 break;
469 case WifiPhyState::TX:
470 NS_LOG_DEBUG("Drop packet because already in Tx");
471 DropPreambleEvent(ppdu, TXING, endRx);
472 break;
473 case WifiPhyState::CCA_BUSY:
475 {
477 m_wifiPhy->m_frameCaptureModel->IsInCaptureWindow(
479 m_wifiPhy->m_frameCaptureModel->CaptureNewFrame(m_wifiPhy->m_currentEvent, event))
480 {
482 NS_LOG_DEBUG("Switch to new packet");
484 }
485 else
486 {
487 NS_LOG_DEBUG("Drop packet because already decoding preamble");
489 }
490 }
491 else
492 {
494 }
495 break;
496 case WifiPhyState::IDLE:
499 break;
500 case WifiPhyState::SLEEP:
501 NS_LOG_DEBUG("Drop packet because in sleep mode");
502 DropPreambleEvent(ppdu, SLEEPING, endRx);
503 break;
504 case WifiPhyState::OFF:
505 NS_LOG_DEBUG("Drop packet because in switched off");
507 break;
508 default:
509 NS_FATAL_ERROR("Invalid WifiPhy state.");
510 break;
511 }
512}
513
514void
516{
517 NS_LOG_FUNCTION(this << ppdu << reason << endRx);
519 auto it = m_wifiPhy->m_currentPreambleEvents.find({ppdu->GetUid(), ppdu->GetPreamble()});
520 if (it != m_wifiPhy->m_currentPreambleEvents.end())
521 {
523 }
525 (endRx > (Simulator::Now() + m_state->GetDelayUntilIdle())))
526 {
527 // that PPDU will be noise _after_ the end of the current event.
529 }
530}
531
532void
534{
535 NS_LOG_FUNCTION(this << ppdu << rxDuration);
536 auto it = m_wifiPhy->m_currentPreambleEvents.find({ppdu->GetUid(), ppdu->GetPreamble()});
537 if (it != m_wifiPhy->m_currentPreambleEvents.end())
538 {
540 }
542 {
543 m_wifiPhy->Reset();
544 }
545
546 if (rxDuration > m_state->GetDelayUntilIdle())
547 {
548 // this PPDU will be noise _after_ the completion of the current event
550 }
551}
552
553uint16_t
555{
556 return SU_STA_ID;
557}
558
559void
561{
562 NS_LOG_FUNCTION(this << *event);
564
565 Time payloadDuration = DoStartReceivePayload(event);
566 m_state->SwitchToRx(payloadDuration);
567}
568
569Time
571{
572 NS_LOG_FUNCTION(this << *event);
573 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
574 NS_LOG_DEBUG("Receiving PSDU");
575 uint16_t staId = GetStaId(ppdu);
576 m_signalNoiseMap.insert({{ppdu->GetUid(), staId}, SignalNoiseDbm()});
577 m_statusPerMpduMap.insert({{ppdu->GetUid(), staId}, std::vector<bool>()});
578 ScheduleEndOfMpdus(event);
579 const auto& txVector = event->GetPpdu()->GetTxVector();
580 Time payloadDuration = ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector);
582 txVector,
583 payloadDuration); // this callback (equivalent to PHY-RXSTART primitive) is triggered only
584 // if headers have been correctly decoded and that the mode within is
585 // supported
586 m_endRxPayloadEvents.push_back(
587 Simulator::Schedule(payloadDuration, &PhyEntity::EndReceivePayload, this, event));
588 return payloadDuration;
589}
590
591void
593{
594 NS_LOG_FUNCTION(this << *event);
595 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
597 const auto& txVector = event->GetPpdu()->GetTxVector();
598 uint16_t staId = GetStaId(ppdu);
599 Time endOfMpduDuration = NanoSeconds(0);
600 Time relativeStart = NanoSeconds(0);
601 Time psduDuration = ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector);
602 Time remainingAmpduDuration = psduDuration;
603 size_t nMpdus = psdu->GetNMpdus();
604 MpduType mpduType =
605 (nMpdus > 1) ? FIRST_MPDU_IN_AGGREGATE : (psdu->IsSingle() ? SINGLE_MPDU : NORMAL_MPDU);
606 uint32_t totalAmpduSize = 0;
607 double totalAmpduNumSymbols = 0.0;
608 auto mpdu = psdu->begin();
609 for (size_t i = 0; i < nMpdus && mpdu != psdu->end(); ++mpdu)
610 {
611 uint32_t size = (mpduType == NORMAL_MPDU) ? psdu->GetSize() : psdu->GetAmpduSubframeSize(i);
612 Time mpduDuration = m_wifiPhy->GetPayloadDuration(size,
613 txVector,
615 mpduType,
616 true,
617 totalAmpduSize,
618 totalAmpduNumSymbols,
619 staId);
620
621 remainingAmpduDuration -= mpduDuration;
622 if (i == (nMpdus - 1) && !remainingAmpduDuration.IsZero()) // no more MPDUs coming
623 {
624 if (remainingAmpduDuration <
625 NanoSeconds(txVector.GetGuardInterval())) // enables to ignore padding
626 {
627 mpduDuration += remainingAmpduDuration; // apply a correction just in case rounding
628 // had induced slight shift
629 }
630 }
631
632 endOfMpduDuration += mpduDuration;
633 NS_LOG_INFO("Schedule end of MPDU #"
634 << i << " in " << endOfMpduDuration.As(Time::NS) << " (relativeStart="
635 << relativeStart.As(Time::NS) << ", mpduDuration=" << mpduDuration.As(Time::NS)
636 << ", remainingAmdpuDuration=" << remainingAmpduDuration.As(Time::NS) << ")");
637 m_endOfMpduEvents.push_back(Simulator::Schedule(endOfMpduDuration,
639 this,
640 event,
641 Create<WifiPsdu>(*mpdu, false),
642 i,
643 relativeStart,
644 mpduDuration));
645
646 // Prepare next iteration
647 ++i;
648 relativeStart += mpduDuration;
649 mpduType = (i == (nMpdus - 1)) ? LAST_MPDU_IN_AGGREGATE : MIDDLE_MPDU_IN_AGGREGATE;
650 }
651}
652
653void
656 size_t mpduIndex,
657 Time relativeStart,
658 Time mpduDuration)
659{
660 NS_LOG_FUNCTION(this << *event << mpduIndex << relativeStart << mpduDuration);
661 const auto ppdu = event->GetPpdu();
662 const auto& txVector = ppdu->GetTxVector();
663 uint16_t staId = GetStaId(ppdu);
664
665 std::pair<bool, SignalNoiseDbm> rxInfo =
666 GetReceptionStatus(psdu, event, staId, relativeStart, mpduDuration);
667 NS_LOG_DEBUG("Extracted MPDU #" << mpduIndex << ": duration: " << mpduDuration.As(Time::NS)
668 << ", correct reception: " << rxInfo.first << ", Signal/Noise: "
669 << rxInfo.second.signal << "/" << rxInfo.second.noise << "dBm");
670
671 auto signalNoiseIt = m_signalNoiseMap.find({ppdu->GetUid(), staId});
672 NS_ASSERT(signalNoiseIt != m_signalNoiseMap.end());
673 signalNoiseIt->second = rxInfo.second;
674
675 RxSignalInfo rxSignalInfo;
676 rxSignalInfo.snr = rxInfo.second.signal / rxInfo.second.noise;
677 rxSignalInfo.rssi = rxInfo.second.signal;
678
679 auto statusPerMpduIt = m_statusPerMpduMap.find({ppdu->GetUid(), staId});
680 NS_ASSERT(statusPerMpduIt != m_statusPerMpduMap.end());
681 statusPerMpduIt->second.push_back(rxInfo.first);
682
683 if (rxInfo.first && GetAddressedPsduInPpdu(ppdu)->GetNMpdus() > 1)
684 {
685 // only done for correct MPDU that is part of an A-MPDU
686 m_state->NotifyRxMpdu(psdu, rxSignalInfo, txVector);
687 }
688}
689
690void
692{
693 const auto ppdu = event->GetPpdu();
694 const auto& txVector = ppdu->GetTxVector();
696 this << *event << ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector));
697 NS_ASSERT(event->GetEndTime() == Simulator::Now());
698 const auto staId = GetStaId(ppdu);
699 const auto channelWidthAndBand = GetChannelWidthAndBand(txVector, staId);
700 double snr = m_wifiPhy->m_interference->CalculateSnr(event,
701 channelWidthAndBand.first,
702 txVector.GetNss(staId),
703 channelWidthAndBand.second);
704
706 m_wifiPhy->NotifyRxEnd(psdu);
707
708 auto signalNoiseIt = m_signalNoiseMap.find({ppdu->GetUid(), staId});
709 NS_ASSERT(signalNoiseIt != m_signalNoiseMap.end());
710 auto statusPerMpduIt = m_statusPerMpduMap.find({ppdu->GetUid(), staId});
711 NS_ASSERT(statusPerMpduIt != m_statusPerMpduMap.end());
712 // store per-MPDU status, which is cleared by the call to DoEndReceivePayload below
713 auto statusPerMpdu = statusPerMpduIt->second;
714
715 RxSignalInfo rxSignalInfo;
716 bool success;
717
718 if (std::count(statusPerMpdu.cbegin(), statusPerMpdu.cend(), true))
719 {
720 // At least one MPDU has been successfully received
723 txVector,
724 signalNoiseIt->second,
725 statusPerMpdu,
726 staId);
727 rxSignalInfo.snr = snr;
728 rxSignalInfo.rssi = signalNoiseIt->second.signal; // same information for all MPDUs
729 RxPayloadSucceeded(psdu, rxSignalInfo, txVector, staId, statusPerMpdu);
731 ppdu->GetUid(); // store UID only if reception is successful (because otherwise trigger
732 // won't be read by MAC layer)
733 success = true;
734 }
735 else
736 {
737 RxPayloadFailed(psdu, snr, txVector);
738 success = false;
739 }
740
743
744 // notify the MAC through the PHY state helper as the last action. Indeed, the notification
745 // of the RX end may lead the MAC to request a PHY state change (e.g., channel switch, sleep).
746 // Hence, all actions the PHY has to perform when RX ends should be completed before
747 // notifying the MAC.
748 success ? m_state->NotifyRxPsduSucceeded(psdu, rxSignalInfo, txVector, staId, statusPerMpdu)
749 : m_state->NotifyRxPsduFailed(psdu, snr);
750}
751
752void
754 RxSignalInfo rxSignalInfo,
755 const WifiTxVector& txVector,
756 uint16_t staId,
757 const std::vector<bool>& statusPerMpdu)
758{
759 NS_LOG_FUNCTION(this << *psdu << txVector);
760 m_state->SwitchFromRxEndOk();
761}
762
763void
765{
766 NS_LOG_FUNCTION(this << *psdu << txVector << snr);
767 m_state->SwitchFromRxEndError();
768}
769
770void
772{
773 NS_LOG_FUNCTION(this << ppdu);
775 NotifyInterferenceRxEndAndClear(false); // don't reset WifiPhy
776
777 m_wifiPhy->m_currentEvent = nullptr;
779 m_endRxPayloadEvents.clear();
780}
781
782std::pair<bool, SignalNoiseDbm>
784 Ptr<Event> event,
785 uint16_t staId,
786 Time relativeMpduStart,
787 Time mpduDuration)
788{
789 NS_LOG_FUNCTION(this << *psdu << *event << staId << relativeMpduStart << mpduDuration);
790 const auto channelWidthAndBand = GetChannelWidthAndBand(event->GetPpdu()->GetTxVector(), staId);
791 SnrPer snrPer = m_wifiPhy->m_interference->CalculatePayloadSnrPer(
792 event,
793 channelWidthAndBand.first,
794 channelWidthAndBand.second,
795 staId,
796 {relativeMpduStart, relativeMpduStart + mpduDuration});
797
798 WifiMode mode = event->GetPpdu()->GetTxVector().GetMode(staId);
799 NS_LOG_DEBUG("rate=" << (mode.GetDataRate(event->GetPpdu()->GetTxVector(), staId))
800 << ", SNR(dB)=" << RatioToDb(snrPer.snr) << ", PER=" << snrPer.per
801 << ", size=" << psdu->GetSize()
802 << ", relativeStart = " << relativeMpduStart.As(Time::NS)
803 << ", duration = " << mpduDuration.As(Time::NS));
804
805 // There are two error checks: PER and receive error model check.
806 // PER check models is typical for Wi-Fi and is based on signal modulation;
807 // Receive error model is optional, if we have an error model and
808 // it indicates that the packet is corrupt, drop the packet.
809 SignalNoiseDbm signalNoise;
810 signalNoise.signal = WToDbm(event->GetRxPowerW(channelWidthAndBand.second));
811 signalNoise.noise = WToDbm(event->GetRxPowerW(channelWidthAndBand.second) / snrPer.snr);
812 if (GetRandomValue() > snrPer.per &&
814 m_wifiPhy->m_postReceptionErrorModel->IsCorrupt(psdu->GetPacket()->Copy())))
815 {
816 NS_LOG_DEBUG("Reception succeeded: " << psdu);
817 return {true, signalNoise};
818 }
819 else
820 {
821 NS_LOG_DEBUG("Reception failed: " << psdu);
822 return {false, signalNoise};
823 }
824}
825
826std::pair<uint16_t, WifiSpectrumBandInfo>
827PhyEntity::GetChannelWidthAndBand(const WifiTxVector& txVector, uint16_t /* staId */) const
828{
829 uint16_t channelWidth = GetRxChannelWidth(txVector);
830 return {channelWidth, GetPrimaryBand(channelWidth)};
831}
832
833const std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
835{
837}
838
839void
841{
842 NS_LOG_FUNCTION(this << *event);
843 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
844 m_wifiPhy->m_currentPreambleEvents.insert({{ppdu->GetUid(), ppdu->GetPreamble()}, event});
845}
846
849{
850 // We store all incoming preamble events, and a decision is made at the end of the preamble
851 // detection window.
852 const auto& currentPreambleEvents = GetCurrentPreambleEvents();
853 const auto it = currentPreambleEvents.find({ppdu->GetUid(), ppdu->GetPreamble()});
854 if (it != currentPreambleEvents.cend())
855 {
856 // received another signal with the same content
857 NS_LOG_DEBUG("Received another PPDU for UID " << ppdu->GetUid());
858 const auto foundEvent = it->second;
859 HandleRxPpduWithSameContent(foundEvent, ppdu, rxPowersW);
860 return nullptr;
861 }
862
863 auto event = CreateInterferenceEvent(ppdu, ppdu->GetTxDuration(), rxPowersW);
864 AddPreambleEvent(event);
865 return event;
866}
867
870 Time duration,
872 bool isStartHePortionRxing /* = false */)
873{
874 return m_wifiPhy->m_interference->Add(ppdu, duration, rxPower, isStartHePortionRxing);
875}
876
877void
881{
882 if (const auto maxDelay =
883 m_wifiPhy->GetPhyEntityForPpdu(ppdu)->GetMaxDelayPpduSameUid(ppdu->GetTxVector());
884 Simulator::Now() - event->GetStartTime() > maxDelay)
885 {
886 // This PPDU arrived too late to be decoded properly. The PPDU is dropped and added as
887 // interference
888 event = CreateInterferenceEvent(ppdu, ppdu->GetTxDuration(), rxPower);
889 NS_LOG_DEBUG("Drop PPDU that arrived too late");
891 return;
892 }
893
894 // Update received power and TXVECTOR of the event associated to that transmission upon
895 // reception of a signal adding up constructively (in case of a UL MU PPDU or non-HT duplicate
896 // PPDU)
897 m_wifiPhy->m_interference->UpdateEvent(event, rxPower);
898 const auto& txVector = ppdu->GetTxVector();
899 const auto& eventTxVector = event->GetPpdu()->GetTxVector();
900 auto updatedTxVector{eventTxVector};
901 updatedTxVector.SetChannelWidth(
902 std::max(eventTxVector.GetChannelWidth(), txVector.GetChannelWidth()));
903 if (updatedTxVector.GetChannelWidth() != eventTxVector.GetChannelWidth())
904 {
905 event->UpdatePpdu(ppdu);
906 }
907}
908
909void
911{
913 m_signalNoiseMap.clear();
914 m_statusPerMpduMap.clear();
915 for (const auto& endOfMpduEvent : m_endOfMpduEvents)
916 {
917 NS_ASSERT(endOfMpduEvent.IsExpired());
918 }
919 m_endOfMpduEvents.clear();
920 if (reset)
921 {
922 m_wifiPhy->Reset();
923 }
924}
925
928{
929 NS_LOG_FUNCTION(this << *event);
931 1); // Synched on one after detection period
932 return PhyFieldRxStatus(true); // always consider that preamble has been correctly received if
933 // preamble detection was OK
934}
935
936void
938{
939 NS_LOG_FUNCTION(this << *event);
940 NS_LOG_DEBUG("Sync to signal (power=" << WToDbm(GetRxPowerWForPpdu(event)) << "dBm)");
942 ->NotifyRxStart(); // We need to notify it now so that it starts recording events
946 this,
947 event));
948}
949
950void
952{
953 NS_LOG_FUNCTION(this << *event);
955 NS_ASSERT(m_wifiPhy->m_endPhyRxEvent.IsExpired()); // since end of preamble reception is
956 // scheduled by this method upon success
957
958 // calculate PER on the measurement channel for PHY headers
959 uint16_t measurementChannelWidth = GetMeasurementChannelWidth(event->GetPpdu());
960 auto measurementBand = GetPrimaryBand(measurementChannelWidth);
961 double maxRxPowerW = -1; // in case current event may not be sent on measurement channel
962 // (rxPowerW would be equal to 0)
963 Ptr<Event> maxEvent;
965 for (auto preambleEvent : m_wifiPhy->m_currentPreambleEvents)
966 {
967 double rxPowerW = preambleEvent.second->GetRxPowerW(measurementBand);
968 if (rxPowerW > maxRxPowerW)
969 {
970 maxRxPowerW = rxPowerW;
971 maxEvent = preambleEvent.second;
972 }
973 }
974
975 NS_ASSERT(maxEvent);
976 if (maxEvent != event)
977 {
978 NS_LOG_DEBUG("Receiver got a stronger packet with UID "
979 << maxEvent->GetPpdu()->GetUid()
980 << " during preamble detection: drop packet with UID "
981 << event->GetPpdu()->GetUid());
983 auto it = m_wifiPhy->m_currentPreambleEvents.find(
984 {event->GetPpdu()->GetUid(), event->GetPpdu()->GetPreamble()});
986 // This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to
987 // the power at the start of the PPDU
988 m_wifiPhy->m_interference->NotifyRxEnd(maxEvent->GetStartTime(),
990 // Make sure InterferenceHelper keeps recording events
991 m_wifiPhy->m_interference->NotifyRxStart();
992 return;
993 }
994
995 m_wifiPhy->m_currentEvent = event;
996
997 double snr = m_wifiPhy->m_interference->CalculateSnr(m_wifiPhy->m_currentEvent,
998 measurementChannelWidth,
999 1,
1000 measurementBand);
1001 NS_LOG_DEBUG("SNR(dB)=" << RatioToDb(snr) << " at end of preamble detection period");
1002
1003 if ((!m_wifiPhy->m_preambleDetectionModel && maxRxPowerW > 0.0) ||
1005 m_wifiPhy->m_preambleDetectionModel->IsPreambleDetected(
1006 m_wifiPhy->m_currentEvent->GetRxPowerW(measurementBand),
1007 snr,
1008 measurementChannelWidth)))
1009 {
1010 // A bit convoluted but it enables to sync all PHYs
1011 for (auto& it : m_wifiPhy->m_phyEntities)
1012 {
1013 it.second->CancelRunningEndPreambleDetectionEvents();
1014 }
1015
1016 for (auto it = m_wifiPhy->m_currentPreambleEvents.begin();
1017 it != m_wifiPhy->m_currentPreambleEvents.end();)
1018 {
1019 if (it->second != m_wifiPhy->m_currentEvent)
1020 {
1021 NS_LOG_DEBUG("Drop packet with UID " << it->first.first << " and preamble "
1022 << it->first.second << " arrived at time "
1023 << it->second->GetStartTime());
1025 if (m_wifiPhy->m_currentEvent->GetPpdu()->GetUid() > it->first.first)
1026 {
1028 // This is needed to cleanup the m_firstPowerPerBand so that the first power
1029 // corresponds to the power at the start of the PPDU
1030 m_wifiPhy->m_interference->NotifyRxEnd(
1031 m_wifiPhy->m_currentEvent->GetStartTime(),
1033 }
1034 else
1035 {
1036 reason = BUSY_DECODING_PREAMBLE;
1037 }
1038 m_wifiPhy->NotifyRxDrop(GetAddressedPsduInPpdu(it->second->GetPpdu()), reason);
1039 it = m_wifiPhy->m_currentPreambleEvents.erase(it);
1040 }
1041 else
1042 {
1043 ++it;
1044 }
1045 }
1046
1047 // Make sure InterferenceHelper keeps recording events
1048 m_wifiPhy->m_interference->NotifyRxStart();
1049
1051 m_wifiPhy->m_currentEvent->GetRxPowerWPerBand());
1053
1054 // Continue receiving preamble
1055 Time durationTillEnd =
1056 GetDuration(WIFI_PPDU_FIELD_PREAMBLE, event->GetPpdu()->GetTxVector()) -
1058 m_wifiPhy->NotifyCcaBusy(event->GetPpdu(),
1059 durationTillEnd); // will be prolonged by next field
1062 this,
1064 event);
1065 }
1066 else
1067 {
1068 NS_LOG_DEBUG("Drop packet because PHY preamble detection failed");
1069 // Like CCA-SD, CCA-ED is governed by the 4 us CCA window to flag CCA-BUSY
1070 // for any received signal greater than the CCA-ED threshold.
1073 m_wifiPhy->m_currentEvent->GetEndTime());
1075 {
1076 // Do not erase events if there are still pending preamble events to be processed
1077 m_wifiPhy->m_interference->NotifyRxEnd(Simulator::Now(),
1079 }
1080 m_wifiPhy->m_currentEvent = nullptr;
1081 // Cancel preamble reception
1083 }
1084}
1085
1086bool
1088{
1089 WifiMode txMode = ppdu->GetTxVector().GetMode();
1090 if (!IsModeSupported(txMode))
1091 {
1092 NS_LOG_DEBUG("Drop packet because it was sent using an unsupported mode (" << txMode
1093 << ")");
1094 return false;
1095 }
1096 return true;
1097}
1098
1099void
1101{
1102 NS_LOG_FUNCTION(this);
1104 for (auto& endRxPayloadEvent : m_endRxPayloadEvents)
1105 {
1106 endRxPayloadEvent.Cancel();
1107 }
1108 m_endRxPayloadEvents.clear();
1109 for (auto& endMpduEvent : m_endOfMpduEvents)
1110 {
1111 endMpduEvent.Cancel();
1112 }
1113 m_endOfMpduEvents.clear();
1114}
1115
1116bool
1118{
1119 return m_endPreambleDetectionEvents.empty();
1120}
1121
1122void
1124{
1125 NS_LOG_FUNCTION(this);
1126 for (auto& endPreambleDetectionEvent : m_endPreambleDetectionEvents)
1127 {
1128 endPreambleDetectionEvent.Cancel();
1129 }
1131}
1132
1133void
1135{
1136 NS_LOG_FUNCTION(this << reason);
1139}
1140
1141void
1143{
1144 NS_LOG_FUNCTION(this << reason);
1145 if (m_wifiPhy->m_currentEvent) // Otherwise abort has already been called just before
1146 {
1147 for (auto& endMpduEvent : m_endOfMpduEvents)
1148 {
1149 endMpduEvent.Cancel();
1150 }
1151 m_endOfMpduEvents.clear();
1152 }
1153}
1154
1155void
1157{
1158 NS_LOG_FUNCTION(this << *event);
1159 DoResetReceive(event);
1162 NS_ASSERT(m_endRxPayloadEvents.size() == 1 && m_endRxPayloadEvents.front().IsExpired());
1163 m_endRxPayloadEvents.clear();
1164 m_wifiPhy->m_currentEvent = nullptr;
1166 m_wifiPhy->SwitchMaybeToCcaBusy(event->GetPpdu());
1167}
1168
1169void
1171{
1172 NS_LOG_FUNCTION(this << *event);
1173 NS_ASSERT(event->GetEndTime() == Simulator::Now());
1174}
1175
1176double
1178{
1179 return m_wifiPhy->m_random->GetValue();
1180}
1181
1182double
1184{
1185 return event->GetRxPowerW(GetPrimaryBand(GetMeasurementChannelWidth(event->GetPpdu())));
1186}
1187
1190{
1191 return m_wifiPhy->m_currentEvent;
1192}
1193
1195PhyEntity::GetPrimaryBand(uint16_t bandWidth) const
1196{
1197 if (m_wifiPhy->GetChannelWidth() % 20 != 0)
1198 {
1199 return m_wifiPhy->GetBand(bandWidth);
1200 }
1201 return m_wifiPhy->GetBand(bandWidth,
1203}
1204
1206PhyEntity::GetSecondaryBand(uint16_t bandWidth) const
1207{
1209 return m_wifiPhy->GetBand(bandWidth,
1211}
1212
1213uint16_t
1215{
1216 return std::min(m_wifiPhy->GetChannelWidth(), txVector.GetChannelWidth());
1217}
1218
1219double
1221 WifiChannelListType /*channelType*/) const
1222{
1224}
1225
1226Time
1228{
1229 return m_wifiPhy->m_interference->GetEnergyDuration(DbmToW(thresholdDbm), band);
1230}
1231
1232void
1234{
1235 // We are here because we have received the first bit of a packet and we are
1236 // not going to be able to synchronize on it
1237 // In this model, CCA becomes busy when the aggregation of all signals as
1238 // tracked by the InterferenceHelper class is higher than the CcaBusyThreshold
1239 const auto ccaIndication = GetCcaIndication(ppdu);
1240 if (ccaIndication.has_value())
1241 {
1242 NS_LOG_DEBUG("CCA busy for " << ccaIndication.value().second << " during "
1243 << ccaIndication.value().first.As(Time::S));
1244 m_state->SwitchMaybeToCcaBusy(ccaIndication.value().first,
1245 ccaIndication.value().second,
1246 {});
1247 return;
1248 }
1249 if (ppdu)
1250 {
1251 SwitchMaybeToCcaBusy(nullptr);
1252 }
1253}
1254
1257{
1258 const uint16_t channelWidth = GetMeasurementChannelWidth(ppdu);
1259 NS_LOG_FUNCTION(this << channelWidth);
1260 const double ccaThresholdDbm = GetCcaThreshold(ppdu, WIFI_CHANLIST_PRIMARY);
1261 const Time delayUntilCcaEnd =
1262 GetDelayUntilCcaEnd(ccaThresholdDbm, GetPrimaryBand(channelWidth));
1263 if (delayUntilCcaEnd.IsStrictlyPositive())
1264 {
1265 return std::make_pair(delayUntilCcaEnd, WIFI_CHANLIST_PRIMARY);
1266 }
1267 return std::nullopt;
1268}
1269
1270void
1272 Time duration,
1273 WifiChannelListType channelType)
1274{
1275 NS_LOG_FUNCTION(this << duration << channelType);
1276 NS_LOG_DEBUG("CCA busy for " << channelType << " during " << duration.As(Time::S));
1277 m_state->SwitchMaybeToCcaBusy(duration, channelType, {});
1278}
1279
1280uint64_t
1282{
1283 NS_LOG_FUNCTION(this);
1284 return m_globalPpduUid++;
1285}
1286
1287Time
1289{
1290 return Seconds(0);
1291}
1292
1293uint16_t
1295{
1296 NS_LOG_FUNCTION(this << txVector);
1297
1299 txVector.GetChannelWidth());
1300}
1301
1302void
1303PhyEntity::NotifyPayloadBegin(const WifiTxVector& txVector, const Time& payloadDuration)
1304{
1305 m_wifiPhy->m_phyRxPayloadBeginTrace(txVector, payloadDuration);
1306}
1307
1308void
1310{
1311 NS_LOG_FUNCTION(this << ppdu);
1312 auto txPowerDbm = m_wifiPhy->GetTxPowerForTransmission(ppdu) + m_wifiPhy->GetTxGain();
1313 auto txVector = ppdu->GetTxVector();
1314 auto txPowerSpectrum = GetTxPowerSpectralDensity(DbmToW(txPowerDbm), ppdu);
1315 Transmit(ppdu->GetTxDuration(), ppdu, txPowerDbm, txPowerSpectrum, "transmission");
1316}
1317
1318void
1321 double txPowerDbm,
1322 Ptr<SpectrumValue> txPowerSpectrum,
1323 const std::string& type)
1324{
1325 NS_LOG_FUNCTION(this << txDuration << ppdu << txPowerDbm << type);
1326 NS_LOG_DEBUG("Start " << type << ": signal power before antenna gain=" << txPowerDbm << "dBm");
1327 auto txParams = Create<WifiSpectrumSignalParameters>();
1328 txParams->duration = txDuration;
1329 txParams->psd = txPowerSpectrum;
1330 txParams->ppdu = ppdu;
1331 NS_LOG_DEBUG("Starting " << type << " with power " << txPowerDbm << " dBm on channel "
1332 << +m_wifiPhy->GetChannelNumber() << " for "
1333 << txParams->duration.As(Time::MS));
1334 NS_LOG_DEBUG("Starting " << type << " with integrated spectrum power "
1335 << WToDbm(Integral(*txPowerSpectrum)) << " dBm; spectrum model Uid: "
1336 << txPowerSpectrum->GetSpectrumModel()->GetUid());
1337 auto spectrumWifiPhy = DynamicCast<SpectrumWifiPhy>(m_wifiPhy);
1338 NS_ASSERT(spectrumWifiPhy);
1339 spectrumWifiPhy->Transmit(txParams);
1340}
1341
1342uint16_t
1343PhyEntity::GetGuardBandwidth(uint16_t currentChannelWidth) const
1344{
1345 return m_wifiPhy->GetGuardBandwidth(currentChannelWidth);
1346}
1347
1348std::tuple<double, double, double>
1350{
1352}
1353
1354Time
1356 const WifiTxVector& txVector,
1357 WifiPhyBand band) const
1358{
1359 NS_ASSERT(psduMap.size() == 1);
1360 const auto& it = psduMap.begin();
1361 return WifiPhy::CalculateTxDuration(it->second->GetSize(), txVector, band, it->first);
1362}
1363
1364bool
1366{
1367 // The PHY shall not issue a PHY-RXSTART.indication primitive in response to a PPDU that does
1368 // not overlap the primary channel
1369 const auto channelWidth = m_wifiPhy->GetChannelWidth();
1370 const auto primaryWidth =
1371 ((channelWidth % 20 == 0) ? 20
1372 : channelWidth); // if the channel width is a multiple of 20 MHz,
1373 // then we consider the primary20 channel
1374 const auto p20CenterFreq =
1376 const auto p20MinFreq = p20CenterFreq - (primaryWidth / 2);
1377 const auto p20MaxFreq = p20CenterFreq + (primaryWidth / 2);
1378 const auto txCenterFreq = ppdu->GetTxCenterFreq();
1379 const auto txChannelWidth = ppdu->GetTxChannelWidth();
1380 const auto minTxFreq = txCenterFreq - txChannelWidth / 2;
1381 const auto maxTxFreq = txCenterFreq + txChannelWidth / 2;
1382 return p20MinFreq >= minTxFreq && p20MaxFreq <= maxTxFreq;
1383}
1384
1387{
1388 return ppdu;
1389}
1390
1391} // 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:1303
virtual void HandleRxPpduWithSameContent(Ptr< Event > event, Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPower)
Handle reception of a PPDU that carries the same content of another PPDU.
Definition: phy-entity.cc:878
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:515
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:753
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:927
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper of the WifiPhy (to make it reachable for child classes)
Definition: phy-entity.h:982
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:764
void EndPreambleDetectionPeriod(Ptr< Event > event)
End the preamble detection period.
Definition: phy-entity.cc:951
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:1271
virtual Ptr< WifiPpdu > BuildPpdu(const WifiConstPsduMap &psdus, const WifiTxVector &txVector, Time ppduDuration)
Build amendment-specific PPDU.
Definition: phy-entity.cc:241
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:1349
virtual uint64_t ObtainNextUid(const WifiTxVector &txVector)
Obtain the next UID for the PPDU to transmit.
Definition: phy-entity.cc:1281
virtual Time DoStartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
Definition: phy-entity.cc:570
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:1227
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:397
bool NoEndPreambleDetectionEvents() const
Definition: phy-entity.cc:1117
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:834
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:1002
Ptr< WifiPhy > m_wifiPhy
Pointer to the owning WifiPhy.
Definition: phy-entity.h:981
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:1319
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:1206
std::vector< EventId > m_endOfMpduEvents
the end of MPDU events (only used for A-MPDUs)
Definition: phy-entity.h:988
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:1220
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:366
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:1100
virtual void DoAbortCurrentReception(WifiPhyRxfailureReason reason)
Perform amendment-specific actions before aborting the current reception.
Definition: phy-entity.cc:1142
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Abort the current reception.
Definition: phy-entity.cc:1134
void EndReceivePayload(Ptr< Event > event)
The last symbol of the PPDU has arrived.
Definition: phy-entity.cc:691
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:1005
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:560
std::vector< EventId > m_endRxPayloadEvents
the end of receive events (only one unless UL MU reception)
Definition: phy-entity.h:991
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:1170
void EndReceiveField(WifiPpduField field, Ptr< Event > event)
End receiving a given field.
Definition: phy-entity.cc:306
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
WifiPpduField GetNextField(WifiPpduField currentField, WifiPreamble preamble) const
Return the field following the provided one.
Definition: phy-entity.cc:159
void CancelRunningEndPreambleDetectionEvents()
Cancel all end preamble detection events.
Definition: phy-entity.cc:1123
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Definition: phy-entity.h:326
double GetRxPowerWForPpdu(Ptr< Event > event) const
Obtain the received power (W) for a given band.
Definition: phy-entity.cc:1183
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:1233
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:910
void StartPreambleDetectionPeriod(Ptr< Event > event)
Start the preamble detection period.
Definition: phy-entity.cc:937
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:252
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:999
virtual bool CanStartRx(Ptr< const WifiPpdu > ppdu) const
Determine whether the PHY shall issue a PHY-RXSTART.indication primitive in response to a given PPDU.
Definition: phy-entity.cc:1365
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:1309
virtual uint16_t GetRxChannelWidth(const WifiTxVector &txVector) const
Return the channel width used in the reception spectrum model.
Definition: phy-entity.cc:1214
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:358
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:554
virtual Time CalculateTxDuration(WifiConstPsduMap psduMap, const WifiTxVector &txVector, WifiPhyBand band) const
Definition: phy-entity.cc:1355
void StartReceiveField(WifiPpduField field, Ptr< Event > event)
Start receiving a given field.
Definition: phy-entity.cc:279
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const
Definition: phy-entity.cc:1343
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:1156
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:969
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:1256
std::list< WifiMode > m_modeList
the list of supported modes
Definition: phy-entity.h:985
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:1288
Ptr< const Event > GetCurrentEvent() const
Get the pointer to the current event (stored in WifiPhy).
Definition: phy-entity.cc:1189
double GetRandomValue() const
Obtain a random value from the WifiPhy's generator.
Definition: phy-entity.cc:1177
std::vector< EventId > m_endPreambleDetectionEvents
the end of preamble detection events
Definition: phy-entity.h:987
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:268
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:533
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:1386
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:840
virtual void DoEndReceivePayload(Ptr< const WifiPpdu > ppdu)
Perform amendment-specific actions at the end of the reception of the payload.
Definition: phy-entity.cc:771
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:1294
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:827
virtual bool IsConfigSupported(Ptr< const WifiPpdu > ppdu) const
Checks if the signaled configuration (excluding bandwidth) is supported by the PHY.
Definition: phy-entity.cc:1087
Ptr< Event > CreateInterferenceEvent(Ptr< const WifiPpdu > ppdu, Time duration, RxPowerWattPerChannelBand &rxPower, bool isStartHePortionRxing=false)
Create an event using WifiPhy's InterferenceHelper class.
Definition: phy-entity.cc:869
PhyRxFailureAction
Action to perform in case of RX failure.
Definition: phy-entity.h:102
@ DROP
drop PPDU and set CCA_BUSY
Definition: phy-entity.h:103
@ IGNORE
ignore the reception
Definition: phy-entity.h:105
@ ABORT
abort reception of PPDU
Definition: phy-entity.h:104
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:783
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:1195
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:654
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:385
void ScheduleEndOfMpdus(Ptr< Event > event)
Schedule end of MPDUs events.
Definition: phy-entity.cc:592
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
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:415
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition: nstime.h:351
@ 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:315
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:1263
double GetCcaEdThreshold() const
Return the CCA energy detection threshold (dBm).
Definition: wifi-phy.cc:499
Ptr< UniformRandomVariable > m_random
Provides uniform random variables.
Definition: wifi-phy.h:1262
void NotifyCcaBusy(const Ptr< const WifiPpdu > ppdu, Time duration)
Notify PHY state helper to switch to CCA busy state,.
Definition: wifi-phy.cc:2112
WifiPhyOperatingChannel m_operatingChannel
Operating channel.
Definition: wifi-phy.h:1494
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:1460
uint16_t GetChannelWidth() const
Definition: wifi-phy.cc:1051
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:1275
EventId m_endPhyRxEvent
the end of PHY receive event
Definition: wifi-phy.h:1270
double GetTxGain() const
Return the transmission gain (dB).
Definition: wifi-phy.cc:575
void NotifyRxDrop(Ptr< const WifiPsdu > psdu, WifiPhyRxfailureReason reason)
Public method used to fire a PhyRxDrop trace.
Definition: wifi-phy.cc:1608
bool IsStateRx() const
Definition: wifi-phy.cc:2057
uint16_t GetFrequency() const
Definition: wifi-phy.cc:1039
static Time GetPreambleDetectionDuration()
Definition: wifi-phy.cc:1448
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Due to newly arrived signal, the current reception cannot be continued and has to be aborted.
Definition: wifi-phy.cc:2119
Ptr< FrameCaptureModel > m_frameCaptureModel
Frame capture model.
Definition: wifi-phy.h:1536
void NotifyRxBegin(Ptr< const WifiPsdu > psdu, const RxPowerWattPerChannelBand &rxPowersW)
Public method used to fire a PhyRxBegin trace.
Definition: wifi-phy.cc:1584
virtual uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const =0
bool IsStateOff() const
Definition: wifi-phy.cc:2081
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1507
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1298
Ptr< ErrorModel > m_postReceptionErrorModel
Error model for receive packet events.
Definition: wifi-phy.h:1539
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1021
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1273
uint8_t GetChannelNumber() const
Return current channel number.
Definition: wifi-phy.cc:1045
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1278
Ptr< PreambleDetectionModel > m_preambleDetectionModel
Preamble detection model.
Definition: wifi-phy.h:1537
void NotifyRxEnd(Ptr< const WifiPsdu > psdu)
Public method used to fire a PhyRxEnd trace.
Definition: wifi-phy.cc:1596
bool IsStateSleep() const
Definition: wifi-phy.cc:2075
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.
void SwitchMaybeToCcaBusy(const Ptr< const WifiPpdu > ppdu=nullptr)
Check if PHY state should move to CCA busy state based on current state of interference tracker.
Definition: wifi-phy.cc:2105
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1260
double GetTxPowerForTransmission(Ptr< const WifiPpdu > ppdu) const
Compute the transmit power for the next transmission.
Definition: wifi-phy.cc:2184
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:1620
Ptr< PhyEntity > GetPhyEntityForPpdu(const Ptr< const WifiPpdu > ppdu) const
Get the supported PHY entity to use for a received PPDU.
Definition: wifi-phy.cc:732
void Reset()
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1854
TracedCallback< WifiTxVector, Time > m_phyRxPayloadBeginTrace
The trace source fired when the reception of the PHY payload (PSDU) begins.
Definition: wifi-phy.h:1425
Time GetLastRxEndTime() const
Return the end time of the last received packet.
Definition: wifi-phy.cc:2099
Time m_timeLastPreambleDetected
Record the time the last preamble was detected.
Definition: wifi-phy.h:1540
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1033
double GetCcaSensitivityThreshold() const
Return the CCA sensitivity threshold (dBm).
Definition: wifi-phy.cc:512
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...
WifiPreamble GetPreambleType() const
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:1350
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
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:159
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:77
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:112
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:147
double snr
SNR in linear scale.
Definition: phy-entity.h:148
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:69
double rssi
RSSI in dBm.
Definition: phy-entity.h:71
double snr
SNR in linear scale.
Definition: phy-entity.h:70
SignalNoiseDbm structure.
Definition: phy-entity.h:55
double noise
noise power in dBm
Definition: phy-entity.h:57
double signal
signal strength in dBm
Definition: phy-entity.h:56
WifiSpectrumBandInfo structure containing info about a spectrum band.