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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Rediet <getachew.redieteab@orange.com>
7 * Sébastien Deronne <sebastien.deronne@gmail.com> (for logic ported from wifi-phy and
8 * spectrum-wifi-phy)
9 * Mathieu Lacage <mathieu.lacage@sophia.inria.fr> (for logic ported from wifi-phy)
10 */
11
12#include "phy-entity.h"
13
14#include "frame-capture-model.h"
15#include "interference-helper.h"
17#include "spectrum-wifi-phy.h"
18#include "wifi-psdu.h"
20#include "wifi-utils.h"
21
22#include "ns3/assert.h"
23#include "ns3/data-rate.h"
24#include "ns3/log.h"
25#include "ns3/packet.h"
26#include "ns3/simulator.h"
27
28#include <algorithm>
29
30#undef NS_LOG_APPEND_CONTEXT
31#define NS_LOG_APPEND_CONTEXT WIFI_PHY_NS_LOG_APPEND_CONTEXT(m_wifiPhy)
32
33namespace ns3
34{
35
36NS_LOG_COMPONENT_DEFINE("PhyEntity");
37
38std::ostream&
39operator<<(std::ostream& os, const PhyEntity::PhyRxFailureAction& action)
40{
41 switch (action)
42 {
43 case PhyEntity::DROP:
44 return (os << "DROP");
46 return (os << "ABORT");
48 return (os << "IGNORE");
49 default:
50 NS_FATAL_ERROR("Unknown action");
51 return (os << "unknown");
52 }
53}
54
55std::ostream&
56operator<<(std::ostream& os, const PhyEntity::PhyFieldRxStatus& status)
57{
58 if (status.isSuccess)
59 {
60 return os << "success";
61 }
62 else
63 {
64 return os << "failure (" << status.reason << "/" << status.actionIfFailure << ")";
65 }
66}
67
68/*******************************************************
69 * Abstract base class for PHY entities
70 *******************************************************/
71
73
80
81void
83{
84 NS_LOG_FUNCTION(this << wifiPhy);
85 m_wifiPhy = wifiPhy;
87}
88
89bool
91{
92 for (const auto& m : m_modeList)
93 {
94 if (m == mode)
95 {
96 return true;
97 }
98 }
99 return false;
100}
101
102uint8_t
104{
105 return m_modeList.size();
106}
107
109PhyEntity::GetMcs(uint8_t /* index */) const
110{
112 "This method should be used only for HtPhy and child classes. Use GetMode instead.");
113 return WifiMode();
114}
115
116bool
117PhyEntity::IsMcsSupported(uint8_t /* index */) const
118{
119 NS_ABORT_MSG("This method should be used only for HtPhy and child classes. Use IsModeSupported "
120 "instead.");
121 return false;
122}
123
124bool
126{
127 return false;
128}
129
130std::list<WifiMode>::const_iterator
132{
133 return m_modeList.begin();
134}
135
136std::list<WifiMode>::const_iterator
138{
139 return m_modeList.end();
140}
141
144{
145 NS_FATAL_ERROR("PPDU field is not a SIG field (no sense in retrieving the signaled mode) or is "
146 "unsupported: "
147 << field);
148 return WifiMode(); // should be overloaded
149}
150
153{
154 const auto& ppduFormats = GetPpduFormats();
155 const auto itPpdu = ppduFormats.find(preamble);
156 if (itPpdu != ppduFormats.end())
157 {
158 const auto itField = std::find(itPpdu->second.begin(), itPpdu->second.end(), currentField);
159 if (itField != itPpdu->second.end())
160 {
161 const auto itNextField = std::next(itField, 1);
162 if (itNextField != itPpdu->second.end())
163 {
164 return *(itNextField);
165 }
166 NS_FATAL_ERROR("No field after " << currentField << " for " << preamble
167 << " for the provided PPDU formats");
168 }
169 else
170 {
171 NS_FATAL_ERROR("Unsupported PPDU field " << currentField << " for " << preamble
172 << " for the provided PPDU formats");
173 }
174 }
175 else
176 {
177 NS_FATAL_ERROR("Unsupported preamble " << preamble << " for the provided PPDU formats");
178 }
179 return WifiPpduField::WIFI_PPDU_FIELD_PREAMBLE; // Silence compiler warning
180}
181
182Time
184{
185 if (field > WIFI_PPDU_FIELD_EHT_SIG)
186 {
187 NS_FATAL_ERROR("Unsupported PPDU field");
188 }
189 return Time(); // should be overloaded
190}
191
192Time
194{
195 Time duration;
196 for (uint8_t field = WIFI_PPDU_FIELD_PREAMBLE; field < WIFI_PPDU_FIELD_DATA; ++field)
197 {
198 duration += GetDuration(static_cast<WifiPpduField>(field), txVector);
199 }
200 return duration;
201}
202
205{
206 return WifiConstPsduMap({{SU_STA_ID, psdu}});
207}
208
211{
212 return ppdu->GetPsdu();
213}
214
216PhyEntity::GetPhyHeaderSections(const WifiTxVector& txVector, Time ppduStart) const
217{
219 WifiPpduField field = WIFI_PPDU_FIELD_PREAMBLE; // preamble always present
220 Time start = ppduStart;
221
222 while (field != WIFI_PPDU_FIELD_DATA)
223 {
224 Time duration = GetDuration(field, txVector);
225 map[field] = {{start, start + duration}, GetSigMode(field, txVector)};
226 // Move to next field
227 start += duration;
228 field = GetNextField(field, txVector.GetPreambleType());
229 }
230 return map;
231}
232
234PhyEntity::BuildPpdu(const WifiConstPsduMap& psdus, const WifiTxVector& txVector, Time ppduDuration)
235{
236 NS_LOG_FUNCTION(this << psdus << txVector << ppduDuration);
237 NS_FATAL_ERROR("This method is unsupported for the base PhyEntity class. Use the overloaded "
238 "version in the amendment-specific subclasses instead!");
239 return Create<WifiPpdu>(psdus.begin()->second,
240 txVector,
241 m_wifiPhy->GetOperatingChannel()); // should be overloaded
242}
243
244Time
246{
247 if (field ==
248 WIFI_PPDU_FIELD_DATA) // this field is not in the map returned by GetPhyHeaderSections
249 {
251 }
252 const auto& sections = GetPhyHeaderSections(txVector, Time());
253 auto it = sections.find(field);
254 NS_ASSERT(it != sections.end());
255 const auto& startStopTimes = it->second.first;
256 return startStopTimes
257 .first; // return the start time of field relatively to the beginning of the PPDU
258}
259
262{
263 const auto measurementChannelWidth = GetMeasurementChannelWidth(event->GetPpdu());
264 return m_wifiPhy->m_interference->CalculatePhyHeaderSnrPer(
265 event,
266 measurementChannelWidth,
267 GetPrimaryBand(measurementChannelWidth),
268 field);
269}
270
271void
273{
274 NS_LOG_FUNCTION(this << field << *event);
275 NS_ASSERT(m_wifiPhy); // no sense if no owner WifiPhy instance
278 "Use the StartReceivePreamble method for preamble reception");
279 // Handle special cases of data reception
280 if (field == WIFI_PPDU_FIELD_DATA)
281 {
282 StartReceivePayload(event);
283 return;
284 }
285
286 bool supported = DoStartReceiveField(field, event);
287 NS_ABORT_MSG_IF(!supported,
288 "Unknown field "
289 << field << " for this PHY entity"); // TODO see what to do if not supported
290 Time duration = GetDuration(field, event->GetPpdu()->GetTxVector());
292 Simulator::Schedule(duration, &PhyEntity::EndReceiveField, this, field, event);
294 event->GetPpdu(),
295 duration); // keep in CCA busy state up to reception of Data (will then switch to RX)
296}
297
298void
300{
301 NS_LOG_FUNCTION(this << field << *event);
302 NS_ASSERT(m_wifiPhy); // no sense if no owner WifiPhy instance
304 PhyFieldRxStatus status = DoEndReceiveField(field, event);
305 const auto& txVector = event->GetPpdu()->GetTxVector();
306 if (status.isSuccess) // move to next field if reception succeeded
307 {
308 StartReceiveField(GetNextField(field, txVector.GetPreambleType()), event);
309 }
310 else
311 {
312 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
313 switch (status.actionIfFailure)
314 {
315 case ABORT:
316 // Abort reception, but consider medium as busy
318 if (event->GetEndTime() > (Simulator::Now() + m_state->GetDelayUntilIdle()))
319 {
321 }
322 break;
323 case DROP:
324 // Notify drop, keep in CCA busy, and perform same processing as IGNORE case
325 if (status.reason == FILTERED)
326 {
327 // PHY-RXSTART is immediately followed by PHY-RXEND (Filtered)
329 txVector,
330 NanoSeconds(0)); // this callback (equivalent to PHY-RXSTART primitive) is also
331 // triggered for filtered PPDUs
332 }
333 m_wifiPhy->NotifyRxPpduDrop(ppdu, status.reason);
335 // no break
336 case IGNORE:
337 // Keep in Rx state and reset at end
338 m_endRxPayloadEvents.push_back(
341 this,
342 event));
343 break;
344 default:
345 NS_FATAL_ERROR("Unknown action in case of failure");
346 }
347 }
348}
349
350Time
352{
353 const auto& txVector = ppdu->GetTxVector();
354 return ppdu->GetTxDuration() -
355 (GetDurationUpToField(field, txVector) + GetDuration(field, txVector));
356}
357
358bool
360{
361 NS_LOG_FUNCTION(this << field << *event);
363 field != WIFI_PPDU_FIELD_DATA); // handled apart for the time being
364 const auto& ppduFormats = GetPpduFormats();
365 auto itFormat = ppduFormats.find(event->GetPpdu()->GetPreamble());
366 if (itFormat != ppduFormats.end())
367 {
368 auto itField = std::find(itFormat->second.begin(), itFormat->second.end(), field);
369 if (itField != itFormat->second.end())
370 {
371 return true; // supported field so we can start receiving
372 }
373 }
374 return false; // unsupported otherwise
375}
376
379{
380 NS_LOG_FUNCTION(this << field << *event);
381 NS_ASSERT(field != WIFI_PPDU_FIELD_DATA); // handled apart for the time being
382 if (field == WIFI_PPDU_FIELD_PREAMBLE)
383 {
384 return DoEndReceivePreamble(event);
385 }
386 return PhyFieldRxStatus(false); // failed reception by default
387}
388
389void
391 RxPowerWattPerChannelBand& rxPowersW,
392 Time rxDuration)
393{
394 // The total RX power corresponds to the maximum over all the bands
395 auto it =
396 std::max_element(rxPowersW.begin(), rxPowersW.end(), [](const auto& p1, const auto& p2) {
397 return p1.second < p2.second;
398 });
399 NS_LOG_FUNCTION(this << ppdu << it->second);
400
401 auto event = DoGetEvent(ppdu, rxPowersW);
402 if (!event)
403 {
404 // PPDU should be simply considered as interference (once it has been accounted for in
405 // InterferenceHelper)
406 return;
407 }
408
409 Time endRx = Simulator::Now() + rxDuration;
410 if (ppdu->IsTruncatedTx())
411 {
412 NS_LOG_DEBUG("Packet reception stopped because transmitter has been switched off");
413 if (endRx > (Simulator::Now() + m_state->GetDelayUntilIdle()))
414 {
416 }
418 return;
419 }
420
421 switch (m_state->GetState())
422 {
424 NS_LOG_DEBUG("Drop packet because of channel switching");
425 /*
426 * Packets received on the upcoming channel are added to the event list
427 * during the switching state. This way the medium can be correctly sensed
428 * when the device listens to the channel for the first time after the
429 * switching e.g. after channel switching, the channel may be sensed as
430 * busy due to other devices' transmissions started before the end of
431 * the switching.
432 */
434 break;
435 case WifiPhyState::RX:
437 m_wifiPhy->m_frameCaptureModel->IsInCaptureWindow(
439 m_wifiPhy->m_frameCaptureModel->CaptureNewFrame(m_wifiPhy->m_currentEvent, event))
440 {
442 NS_LOG_DEBUG("Switch to new packet");
444 }
445 else
446 {
447 NS_LOG_DEBUG("Drop packet because already in Rx");
448 DropPreambleEvent(ppdu, RXING, endRx);
450 {
451 /*
452 * We are here because the non-legacy PHY header has not been successfully received.
453 * The PHY is kept in RX state for the duration of the PPDU, but EndReceive function
454 * is not called when the reception of the PPDU is finished, which is responsible to
455 * clear m_currentPreambleEvents. As a result, m_currentPreambleEvents should be
456 * cleared here.
457 */
459 }
460 }
461 break;
462 case WifiPhyState::TX:
463 NS_LOG_DEBUG("Drop packet because already in Tx");
464 DropPreambleEvent(ppdu, TXING, endRx);
465 break;
468 {
470 m_wifiPhy->m_frameCaptureModel->IsInCaptureWindow(
472 m_wifiPhy->m_frameCaptureModel->CaptureNewFrame(m_wifiPhy->m_currentEvent, event))
473 {
475 NS_LOG_DEBUG("Switch to new packet");
477 }
478 else
479 {
480 NS_LOG_DEBUG("Drop packet because already decoding preamble");
482 }
483 }
484 else
485 {
487 }
488 break;
492 break;
494 NS_LOG_DEBUG("Drop packet because in sleep mode");
495 DropPreambleEvent(ppdu, SLEEPING, endRx);
496 break;
498 NS_LOG_DEBUG("Drop packet because in switched off");
500 break;
501 default:
502 NS_FATAL_ERROR("Invalid WifiPhy state.");
503 break;
504 }
505}
506
507void
509{
510 NS_LOG_FUNCTION(this << ppdu << reason << endRx);
511 m_wifiPhy->NotifyRxPpduDrop(ppdu, reason);
512 auto it = m_wifiPhy->m_currentPreambleEvents.find({ppdu->GetUid(), ppdu->GetPreamble()});
513 if (it != m_wifiPhy->m_currentPreambleEvents.end())
514 {
516 }
518 (endRx > (Simulator::Now() + m_state->GetDelayUntilIdle())))
519 {
520 // that PPDU will be noise _after_ the end of the current event.
522 }
523}
524
525void
527{
528 NS_LOG_FUNCTION(this << ppdu << rxDuration);
529 auto it = m_wifiPhy->m_currentPreambleEvents.find({ppdu->GetUid(), ppdu->GetPreamble()});
530 if (it != m_wifiPhy->m_currentPreambleEvents.end())
531 {
533 }
535 {
536 m_wifiPhy->Reset();
537 }
538
539 if (rxDuration > m_state->GetDelayUntilIdle())
540 {
541 // this PPDU will be noise _after_ the completion of the current event
543 }
544}
545
546uint16_t
548{
549 return SU_STA_ID;
550}
551
552void
554{
555 NS_LOG_FUNCTION(this << *event);
557
558 Time payloadDuration = DoStartReceivePayload(event);
559 m_state->SwitchToRx(payloadDuration);
560}
561
562Time
564{
565 NS_LOG_FUNCTION(this << *event);
566 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
567 NS_LOG_DEBUG("Receiving PSDU");
568 uint16_t staId = GetStaId(ppdu);
569 m_signalNoiseMap.insert({{ppdu->GetUid(), staId}, SignalNoiseDbm()});
570 m_statusPerMpduMap.insert({{ppdu->GetUid(), staId}, std::vector<bool>()});
571 ScheduleEndOfMpdus(event);
572 const auto& txVector = event->GetPpdu()->GetTxVector();
573 Time payloadDuration = ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector);
575 txVector,
576 payloadDuration); // this callback (equivalent to PHY-RXSTART primitive) is triggered only
577 // if headers have been correctly decoded and that the mode within is
578 // supported
579 m_endRxPayloadEvents.push_back(
580 Simulator::Schedule(payloadDuration, &PhyEntity::EndReceivePayload, this, event));
581 return payloadDuration;
582}
583
584void
586{
587 NS_LOG_FUNCTION(this << *event);
588 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
590 const auto& txVector = event->GetPpdu()->GetTxVector();
591 uint16_t staId = GetStaId(ppdu);
592 Time endOfMpduDuration;
593 Time relativeStart;
594 Time psduDuration = ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector);
595 Time remainingAmpduDuration = psduDuration;
596 size_t nMpdus = psdu->GetNMpdus();
597 MpduType mpduType =
598 (nMpdus > 1) ? FIRST_MPDU_IN_AGGREGATE : (psdu->IsSingle() ? SINGLE_MPDU : NORMAL_MPDU);
599 uint32_t totalAmpduSize = 0;
600 double totalAmpduNumSymbols = 0.0;
601 auto mpdu = psdu->begin();
602 for (size_t i = 0; i < nMpdus && mpdu != psdu->end(); ++mpdu)
603 {
605 {
606 // calculate MAC header size (including A-MPDU subframe header, if present)
607 auto macHdrSize =
608 (*mpdu)->GetHeader().GetSerializedSize() + (mpduType == NORMAL_MPDU ? 0 : 4);
609 // calculate the (approximate) duration of the MAC header TX
610 auto macHdrDuration = DataRate(txVector.GetMode(staId).GetDataRate(txVector, staId))
611 .CalculateBytesTxTime(macHdrSize);
612 const auto widthBand = GetChannelWidthAndBand(txVector, staId);
613 const auto snrPer = m_wifiPhy->m_interference->CalculatePayloadSnrPer(
614 event,
615 widthBand.first,
616 widthBand.second,
617 staId,
618 {relativeStart, relativeStart + macHdrDuration});
619 if (GetRandomValue() > snrPer.per)
620 {
621 // interference level should permit to correctly decode the MAC header
622 m_endOfMacHdrEvents[staId].push_back(
623 Simulator::Schedule(endOfMpduDuration + macHdrDuration, [=, this]() {
624 m_wifiPhy->m_phyRxMacHeaderEndTrace((*mpdu)->GetHeader(),
625 txVector,
626 remainingAmpduDuration -
627 macHdrDuration);
628 }));
629 }
630 }
631
632 uint32_t size = (mpduType == NORMAL_MPDU) ? psdu->GetSize() : psdu->GetAmpduSubframeSize(i);
633 Time mpduDuration = WifiPhy::GetPayloadDuration(size,
634 txVector,
636 mpduType,
637 true,
638 totalAmpduSize,
639 totalAmpduNumSymbols,
640 staId);
641
642 remainingAmpduDuration -= mpduDuration;
643 if (i == (nMpdus - 1) && !remainingAmpduDuration.IsZero()) // no more MPDUs coming
644 {
645 if (remainingAmpduDuration < txVector.GetGuardInterval()) // enables to ignore padding
646 {
647 mpduDuration += remainingAmpduDuration; // apply a correction just in case rounding
648 // had induced slight shift
649 }
650 }
651
652 endOfMpduDuration += mpduDuration;
653 NS_LOG_INFO("Schedule end of MPDU #"
654 << i << " in " << endOfMpduDuration.As(Time::NS) << " (relativeStart="
655 << relativeStart.As(Time::NS) << ", mpduDuration=" << mpduDuration.As(Time::NS)
656 << ", remainingAmdpuDuration=" << remainingAmpduDuration.As(Time::NS) << ")");
657 m_endOfMpduEvents.push_back(Simulator::Schedule(endOfMpduDuration,
659 this,
660 event,
661 *mpdu,
662 i,
663 relativeStart,
664 mpduDuration));
665
666 // Prepare next iteration
667 ++i;
668 relativeStart += mpduDuration;
669 mpduType = (i == (nMpdus - 1)) ? LAST_MPDU_IN_AGGREGATE : MIDDLE_MPDU_IN_AGGREGATE;
670 }
671}
672
673void
675 Ptr<WifiMpdu> mpdu,
676 size_t mpduIndex,
677 Time relativeStart,
678 Time mpduDuration)
679{
680 NS_LOG_FUNCTION(this << *event << mpduIndex << relativeStart << mpduDuration);
681 const auto ppdu = event->GetPpdu();
682 const auto& txVector = ppdu->GetTxVector();
683 uint16_t staId = GetStaId(ppdu);
684
685 std::pair<bool, SignalNoiseDbm> rxInfo =
686 GetReceptionStatus(mpdu, event, staId, relativeStart, mpduDuration);
687 NS_LOG_DEBUG("Extracted MPDU #" << mpduIndex << ": duration: " << mpduDuration.As(Time::NS)
688 << ", correct reception: " << rxInfo.first << ", Signal/Noise: "
689 << rxInfo.second.signal << "/" << rxInfo.second.noise << "dBm");
690
691 auto signalNoiseIt = m_signalNoiseMap.find({ppdu->GetUid(), staId});
692 NS_ASSERT(signalNoiseIt != m_signalNoiseMap.end());
693 signalNoiseIt->second = rxInfo.second;
694
695 RxSignalInfo rxSignalInfo;
696 rxSignalInfo.snr = DbToRatio(dB_u{rxInfo.second.signal - rxInfo.second.noise});
697 rxSignalInfo.rssi = rxInfo.second.signal;
698
699 auto statusPerMpduIt = m_statusPerMpduMap.find({ppdu->GetUid(), staId});
700 NS_ASSERT(statusPerMpduIt != m_statusPerMpduMap.end());
701 statusPerMpduIt->second.push_back(rxInfo.first);
702
703 if (rxInfo.first && GetAddressedPsduInPpdu(ppdu)->GetNMpdus() > 1)
704 {
705 // only done for correct MPDU that is part of an A-MPDU
706 m_state->NotifyRxMpdu(Create<const WifiPsdu>(mpdu, false), rxSignalInfo, txVector);
707 }
708}
709
710void
712{
713 const auto ppdu = event->GetPpdu();
714 const auto& txVector = ppdu->GetTxVector();
716 this << *event << ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector));
717 NS_ASSERT(event->GetEndTime() == Simulator::Now());
718 const auto staId = GetStaId(ppdu);
719 const auto channelWidthAndBand = GetChannelWidthAndBand(txVector, staId);
720 const auto snr = m_wifiPhy->m_interference->CalculateSnr(event,
721 channelWidthAndBand.first,
722 txVector.GetNss(staId),
723 channelWidthAndBand.second);
724
726 m_wifiPhy->NotifyRxEnd(psdu);
727
728 auto signalNoiseIt = m_signalNoiseMap.find({ppdu->GetUid(), staId});
729 NS_ASSERT(signalNoiseIt != m_signalNoiseMap.end());
730 auto statusPerMpduIt = m_statusPerMpduMap.find({ppdu->GetUid(), staId});
731 NS_ASSERT(statusPerMpduIt != m_statusPerMpduMap.end());
732 // store per-MPDU status, which is cleared by the call to DoEndReceivePayload below
733 auto statusPerMpdu = statusPerMpduIt->second;
734
735 RxSignalInfo rxSignalInfo;
736 bool success;
737
738 if (std::count(statusPerMpdu.cbegin(), statusPerMpdu.cend(), true))
739 {
740 // At least one MPDU has been successfully received
743 txVector,
744 signalNoiseIt->second,
745 statusPerMpdu,
746 staId);
747 rxSignalInfo.snr = snr;
748 rxSignalInfo.rssi = signalNoiseIt->second.signal; // same information for all MPDUs
749 RxPayloadSucceeded(psdu, rxSignalInfo, txVector, staId, statusPerMpdu);
751 ppdu->GetUid(); // store UID only if reception is successful (because otherwise trigger
752 // won't be read by MAC layer)
753 success = true;
754 }
755 else
756 {
757 RxPayloadFailed(psdu, snr, txVector);
758 success = false;
759 }
760
761 m_state->NotifyRxPpduOutcome(ppdu, rxSignalInfo, txVector, staId, statusPerMpduIt->second);
764
765 // notify the MAC through the PHY state helper as the last action. Indeed, the notification
766 // of the RX end may lead the MAC to request a PHY state change (e.g., channel switch, sleep).
767 // Hence, all actions the PHY has to perform when RX ends should be completed before
768 // notifying the MAC.
769 success ? m_state->NotifyRxPsduSucceeded(psdu, rxSignalInfo, txVector, staId, statusPerMpdu)
770 : m_state->NotifyRxPsduFailed(psdu, snr);
771}
772
773void
775 RxSignalInfo rxSignalInfo,
776 const WifiTxVector& txVector,
777 uint16_t staId,
778 const std::vector<bool>& statusPerMpdu)
779{
780 NS_LOG_FUNCTION(this << *psdu << txVector);
781 m_state->SwitchFromRxEndOk();
782}
783
784void
786{
787 NS_LOG_FUNCTION(this << *psdu << txVector << snr);
788 m_state->SwitchFromRxEndError(txVector);
789}
790
791void
802
803std::pair<bool, SignalNoiseDbm>
805 Ptr<Event> event,
806 uint16_t staId,
807 Time relativeMpduStart,
808 Time mpduDuration)
809{
810 NS_LOG_FUNCTION(this << *mpdu << *event << staId << relativeMpduStart << mpduDuration);
811 const auto channelWidthAndBand = GetChannelWidthAndBand(event->GetPpdu()->GetTxVector(), staId);
812 SnrPer snrPer = m_wifiPhy->m_interference->CalculatePayloadSnrPer(
813 event,
814 channelWidthAndBand.first,
815 channelWidthAndBand.second,
816 staId,
817 {relativeMpduStart, relativeMpduStart + mpduDuration});
818
819 WifiMode mode = event->GetPpdu()->GetTxVector().GetMode(staId);
820 NS_LOG_DEBUG("rate=" << (mode.GetDataRate(event->GetPpdu()->GetTxVector(), staId))
821 << ", SNR(dB)=" << RatioToDb(snrPer.snr) << ", PER=" << snrPer.per
822 << ", size=" << mpdu->GetSize()
823 << ", relativeStart = " << relativeMpduStart.As(Time::NS)
824 << ", duration = " << mpduDuration.As(Time::NS));
825
826 // There are two error checks: PER and receive error model check.
827 // PER check models is typical for Wi-Fi and is based on signal modulation;
828 // Receive error model is optional, if we have an error model and
829 // it indicates that the packet is corrupt, drop the packet.
830 SignalNoiseDbm signalNoise;
831 signalNoise.signal = WToDbm(event->GetRxPower(channelWidthAndBand.second));
832 signalNoise.noise = WToDbm(event->GetRxPower(channelWidthAndBand.second) / snrPer.snr);
833 if (GetRandomValue() > snrPer.per &&
835 m_wifiPhy->m_postReceptionErrorModel->IsCorrupt(mpdu->GetPacket()->Copy())))
836 {
837 NS_LOG_DEBUG("Reception succeeded: " << *mpdu);
838 return {true, signalNoise};
839 }
840 else
841 {
842 NS_LOG_DEBUG("Reception failed: " << *mpdu);
843 return {false, signalNoise};
844 }
845}
846
847std::optional<Time>
849{
851 {
852 return {};
853 }
854
855 std::optional<Time> delayUntilPreambleDetectionEnd;
856 for (const auto& endPreambleDetectionEvent : m_endPreambleDetectionEvents)
857 {
858 if (endPreambleDetectionEvent.IsPending())
859 {
860 delayUntilPreambleDetectionEnd =
861 std::max(delayUntilPreambleDetectionEnd.value_or(Time{0}),
862 Simulator::GetDelayLeft(endPreambleDetectionEvent));
863 }
864 }
865 return delayUntilPreambleDetectionEnd;
866}
867
868std::optional<Time>
869PhyEntity::GetTimeToMacHdrEnd(uint16_t staId) const
870{
871 const auto it = m_endOfMacHdrEvents.find(staId);
872
873 if (it == m_endOfMacHdrEvents.cend())
874 {
875 return std::nullopt;
876 }
877
878 for (const auto& endOfMacHdrEvent : it->second)
879 {
880 if (endOfMacHdrEvent.IsPending())
881 {
882 return Simulator::GetDelayLeft(endOfMacHdrEvent);
883 }
884 }
885
886 return std::nullopt;
887}
888
889std::pair<MHz_u, WifiSpectrumBandInfo>
890PhyEntity::GetChannelWidthAndBand(const WifiTxVector& txVector, uint16_t /* staId */) const
891{
892 const auto channelWidth = GetRxChannelWidth(txVector);
893 return {channelWidth, GetPrimaryBand(channelWidth)};
894}
895
896const std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
901
902void
904{
905 NS_LOG_FUNCTION(this << *event);
906 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
907 m_wifiPhy->m_currentPreambleEvents.insert({{ppdu->GetUid(), ppdu->GetPreamble()}, event});
908}
909
912{
913 // We store all incoming preamble events, and a decision is made at the end of the preamble
914 // detection window.
915 const auto& currentPreambleEvents = GetCurrentPreambleEvents();
916 const auto it = currentPreambleEvents.find({ppdu->GetUid(), ppdu->GetPreamble()});
917 if (it != currentPreambleEvents.cend())
918 {
919 // received another signal with the same content
920 NS_LOG_DEBUG("Received another PPDU for UID " << ppdu->GetUid());
921 const auto foundEvent = it->second;
922 HandleRxPpduWithSameContent(foundEvent, ppdu, rxPowersW);
923 return nullptr;
924 }
925
926 auto event = CreateInterferenceEvent(ppdu, ppdu->GetTxDuration(), rxPowersW);
927 AddPreambleEvent(event);
928 return event;
929}
930
933 Time duration,
935 bool isStartHePortionRxing /* = false */)
936{
937 return m_wifiPhy->m_interference->Add(ppdu,
938 duration,
939 rxPower,
941 isStartHePortionRxing);
942}
943
944void
948{
949 if (const auto maxDelay =
950 m_wifiPhy->GetPhyEntityForPpdu(ppdu)->GetMaxDelayPpduSameUid(ppdu->GetTxVector());
951 Simulator::Now() - event->GetStartTime() > maxDelay)
952 {
953 // This PPDU arrived too late to be decoded properly. The PPDU is dropped and added as
954 // interference
955 event = CreateInterferenceEvent(ppdu, ppdu->GetTxDuration(), rxPower);
956 NS_LOG_DEBUG("Drop PPDU that arrived too late");
958 return;
959 }
960
961 // Update received power and TXVECTOR of the event associated to that transmission upon
962 // reception of a signal adding up constructively (in case of a UL MU PPDU or non-HT duplicate
963 // PPDU)
964 m_wifiPhy->m_interference->UpdateEvent(event, rxPower);
965 const auto& txVector = ppdu->GetTxVector();
966 const auto& eventTxVector = event->GetPpdu()->GetTxVector();
967 auto updatedTxVector{eventTxVector};
968 updatedTxVector.SetChannelWidth(
969 std::max(eventTxVector.GetChannelWidth(), txVector.GetChannelWidth()));
970 if (updatedTxVector.GetChannelWidth() != eventTxVector.GetChannelWidth())
971 {
972 event->UpdatePpdu(ppdu);
973 }
974}
975
976void
978{
980 m_signalNoiseMap.clear();
981 m_statusPerMpduMap.clear();
982 for (const auto& endOfMpduEvent : m_endOfMpduEvents)
983 {
984 NS_ASSERT(endOfMpduEvent.IsExpired());
985 }
986 m_endOfMpduEvents.clear();
987 for (const auto& [staId, endOfMacHdrEvents] : m_endOfMacHdrEvents)
988 {
989 for (const auto& endOfMacHdrEvent : endOfMacHdrEvents)
990 {
991 NS_ASSERT(endOfMacHdrEvent.IsExpired());
992 }
993 }
994 m_endOfMacHdrEvents.clear();
995 if (reset)
996 {
997 m_wifiPhy->Reset();
998 }
999}
1000
1003{
1004 NS_LOG_FUNCTION(this << *event);
1006 1); // Synched on one after detection period
1007 return PhyFieldRxStatus(true); // always consider that preamble has been correctly received if
1008 // preamble detection was OK
1009}
1010
1011void
1013{
1014 NS_LOG_FUNCTION(this << *event);
1015 const auto rxPower = GetRxPowerForPpdu(event);
1016 NS_LOG_DEBUG("Sync to signal (power=" << (rxPower > Watt_u{0.0}
1017 ? std::to_string(WToDbm(rxPower)) + "dBm)"
1018 : std::to_string(rxPower) + "W)"));
1019 m_wifiPhy->m_interference->NotifyRxStart(
1020 m_wifiPhy->GetCurrentFrequencyRange()); // We need to notify it now so that it starts
1021 // recording events
1025 this,
1026 event));
1027}
1028
1029void
1031{
1032 NS_LOG_FUNCTION(this << *event);
1034 NS_ASSERT(m_wifiPhy->m_endPhyRxEvent.IsExpired()); // since end of preamble reception is
1035 // scheduled by this method upon success
1036
1037 // calculate PER on the measurement channel for PHY headers
1038 const auto measurementChannelWidth = GetMeasurementChannelWidth(event->GetPpdu());
1039 auto measurementBand = GetPrimaryBand(measurementChannelWidth);
1040 std::optional<Watt_u>
1041 maxRxPower; // in case current event may not be sent on measurement channel
1042 Ptr<Event> maxEvent;
1044 for (auto preambleEvent : m_wifiPhy->m_currentPreambleEvents)
1045 {
1046 const auto rxPower = preambleEvent.second->GetRxPower(measurementBand);
1047 if (!maxRxPower || (rxPower > *maxRxPower))
1048 {
1049 maxRxPower = rxPower;
1050 maxEvent = preambleEvent.second;
1051 }
1052 }
1053
1054 NS_ASSERT(maxEvent);
1055 if (maxEvent != event)
1056 {
1057 NS_LOG_DEBUG("Receiver got a stronger packet with UID "
1058 << maxEvent->GetPpdu()->GetUid()
1059 << " during preamble detection: drop packet with UID "
1060 << event->GetPpdu()->GetUid());
1062
1063 auto it = m_wifiPhy->m_currentPreambleEvents.find(
1064 {event->GetPpdu()->GetUid(), event->GetPpdu()->GetPreamble()});
1066 // This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to
1067 // the power at the start of the PPDU
1068 m_wifiPhy->m_interference->NotifyRxEnd(maxEvent->GetStartTime(),
1070 // Make sure InterferenceHelper keeps recording events
1072 return;
1073 }
1074
1075 m_wifiPhy->m_currentEvent = event;
1076
1077 const auto snr = m_wifiPhy->m_interference->CalculateSnr(m_wifiPhy->m_currentEvent,
1078 measurementChannelWidth,
1079 1,
1080 measurementBand);
1081 NS_LOG_DEBUG("SNR(dB)=" << RatioToDb(snr) << " at end of preamble detection period");
1082
1083 if (const auto power = m_wifiPhy->m_currentEvent->GetRxPower(measurementBand);
1084 (!m_wifiPhy->m_preambleDetectionModel && maxRxPower && (*maxRxPower > Watt_u{0.0})) ||
1085 (m_wifiPhy->m_preambleDetectionModel && power > Watt_u{0.0} &&
1086 m_wifiPhy->m_preambleDetectionModel->IsPreambleDetected(WToDbm(power),
1087 snr,
1088 measurementChannelWidth)))
1089 {
1090 // A bit convoluted but it enables to sync all PHYs
1091 for (auto& it : m_wifiPhy->m_phyEntities)
1092 {
1093 it.second->CancelRunningEndPreambleDetectionEvents();
1094 }
1095
1096 for (auto it = m_wifiPhy->m_currentPreambleEvents.begin();
1097 it != m_wifiPhy->m_currentPreambleEvents.end();)
1098 {
1099 if (it->second != m_wifiPhy->m_currentEvent)
1100 {
1101 NS_LOG_DEBUG("Drop packet with UID " << it->first.first << " and preamble "
1102 << it->first.second << " arrived at time "
1103 << it->second->GetStartTime());
1105 if (m_wifiPhy->m_currentEvent->GetPpdu()->GetUid() > it->first.first)
1106 {
1108 // This is needed to cleanup the m_firstPowerPerBand so that the first power
1109 // corresponds to the power at the start of the PPDU
1110 m_wifiPhy->m_interference->NotifyRxEnd(
1111 m_wifiPhy->m_currentEvent->GetStartTime(),
1113 }
1114 else
1115 {
1116 reason = BUSY_DECODING_PREAMBLE;
1117 }
1118 m_wifiPhy->NotifyRxPpduDrop(it->second->GetPpdu(), reason);
1119
1120 it = m_wifiPhy->m_currentPreambleEvents.erase(it);
1121 }
1122 else
1123 {
1124 ++it;
1125 }
1126 }
1127
1128 // Make sure InterferenceHelper keeps recording events
1130
1132 m_wifiPhy->m_currentEvent->GetRxPowerPerBand());
1134
1135 // Continue receiving preamble
1136 const auto durationTillEnd =
1137 GetDuration(WIFI_PPDU_FIELD_PREAMBLE, event->GetPpdu()->GetTxVector()) -
1139 m_wifiPhy->NotifyCcaBusy(event->GetPpdu(),
1140 durationTillEnd); // will be prolonged by next field
1143 this,
1145 event);
1146 }
1147 else
1148 {
1149 NS_LOG_DEBUG("Drop packet because PHY preamble detection failed");
1150 // Like CCA-SD, CCA-ED is governed by the 4 us CCA window to flag CCA-BUSY
1151 // for any received signal greater than the CCA-ED threshold.
1154 m_wifiPhy->m_currentEvent->GetEndTime());
1156 {
1157 // Do not erase events if there are still pending preamble events to be processed
1158 m_wifiPhy->m_interference->NotifyRxEnd(Simulator::Now(),
1160 }
1161 m_wifiPhy->m_currentEvent = nullptr;
1162 // Cancel preamble reception
1164 }
1165}
1166
1167bool
1169{
1170 WifiMode txMode = ppdu->GetTxVector().GetMode();
1171 if (!IsModeSupported(txMode))
1172 {
1173 NS_LOG_DEBUG("Drop packet because it was sent using an unsupported mode (" << txMode
1174 << ")");
1175 return false;
1176 }
1177 return true;
1178}
1179
1180void
1182{
1183 NS_LOG_FUNCTION(this);
1185 for (auto& endRxPayloadEvent : m_endRxPayloadEvents)
1186 {
1187 endRxPayloadEvent.Cancel();
1188 }
1189 m_endRxPayloadEvents.clear();
1190 for (auto& endMpduEvent : m_endOfMpduEvents)
1191 {
1192 endMpduEvent.Cancel();
1193 }
1194 m_endOfMpduEvents.clear();
1195 for (auto& [staId, endOfMacHdrEvents] : m_endOfMacHdrEvents)
1196 {
1197 for (auto& endMacHdrEvent : endOfMacHdrEvents)
1198 {
1199 endMacHdrEvent.Cancel();
1200 }
1201 }
1202 m_endOfMacHdrEvents.clear();
1203}
1204
1205void
1207{
1208 NS_LOG_FUNCTION(this);
1209 for (auto& endPreambleDetectionEvent : m_endPreambleDetectionEvents)
1210 {
1211 endPreambleDetectionEvent.Cancel();
1212 }
1214}
1215
1216void
1223
1224void
1226{
1227 NS_LOG_FUNCTION(this << reason);
1228 if (m_wifiPhy->m_currentEvent) // Otherwise abort has already been called just before
1229 {
1230 for (auto& endMpduEvent : m_endOfMpduEvents)
1231 {
1232 endMpduEvent.Cancel();
1233 }
1234 m_endOfMpduEvents.clear();
1235 for (auto& [staId, endOfMacHdrEvents] : m_endOfMacHdrEvents)
1236 {
1237 for (auto& endMacHdrEvent : endOfMacHdrEvents)
1238 {
1239 endMacHdrEvent.Cancel();
1240 }
1241 }
1242 m_endOfMacHdrEvents.clear();
1243 }
1244}
1245
1246void
1248{
1249 NS_LOG_FUNCTION(this << *event);
1250 DoResetReceive(event);
1253 NS_ASSERT(m_endRxPayloadEvents.size() == 1 && m_endRxPayloadEvents.front().IsExpired());
1254 m_endRxPayloadEvents.clear();
1255 m_wifiPhy->m_currentEvent = nullptr;
1257 m_wifiPhy->SwitchMaybeToCcaBusy(event->GetPpdu());
1258}
1259
1260void
1262{
1263 NS_LOG_FUNCTION(this << *event);
1264 NS_ASSERT(event->GetEndTime() == Simulator::Now());
1265}
1266
1267double
1269{
1270 return m_wifiPhy->m_random->GetValue();
1271}
1272
1273Watt_u
1275{
1276 return event->GetRxPower(GetPrimaryBand(GetMeasurementChannelWidth(event->GetPpdu())));
1277}
1278
1281{
1282 return m_wifiPhy->m_currentEvent;
1283}
1284
1287{
1288 if (static_cast<uint16_t>(m_wifiPhy->GetChannelWidth()) % 20 != 0)
1289 {
1290 return m_wifiPhy->GetBand(bandWidth);
1291 }
1292 return m_wifiPhy->GetBand(bandWidth,
1294}
1295
1298{
1300 return m_wifiPhy->GetBand(bandWidth,
1302}
1303
1304MHz_u
1306{
1307 return std::min(m_wifiPhy->GetChannelWidth(), txVector.GetChannelWidth());
1308}
1309
1310dBm_u
1312 WifiChannelListType /*channelType*/) const
1313{
1315}
1316
1317Time
1319{
1320 return m_wifiPhy->m_interference->GetEnergyDuration(DbmToW(threshold), band);
1321}
1322
1323void
1325{
1326 // We are here because we have received the first bit of a packet and we are
1327 // not going to be able to synchronize on it
1328 // In this model, CCA becomes busy when the aggregation of all signals as
1329 // tracked by the InterferenceHelper class is higher than the CcaBusyThreshold
1330 const auto ccaIndication = GetCcaIndication(ppdu);
1331 if (ccaIndication.has_value())
1332 {
1333 NS_LOG_DEBUG("CCA busy for " << ccaIndication.value().second << " during "
1334 << ccaIndication.value().first.As(Time::S));
1335 m_state->SwitchMaybeToCcaBusy(ccaIndication.value().first,
1336 ccaIndication.value().second,
1337 {});
1338 return;
1339 }
1340 if (ppdu)
1341 {
1342 SwitchMaybeToCcaBusy(nullptr);
1343 }
1344}
1345
1348{
1349 const auto channelWidth = GetMeasurementChannelWidth(ppdu);
1350 NS_LOG_FUNCTION(this << channelWidth);
1351 const auto ccaThreshold = GetCcaThreshold(ppdu, WIFI_CHANLIST_PRIMARY);
1352 const Time delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, GetPrimaryBand(channelWidth));
1353 if (delayUntilCcaEnd.IsStrictlyPositive())
1354 {
1355 return std::make_pair(delayUntilCcaEnd, WIFI_CHANLIST_PRIMARY);
1356 }
1357 return std::nullopt;
1358}
1359
1360void
1362 Time duration,
1363 WifiChannelListType channelType)
1364{
1365 NS_LOG_FUNCTION(this << duration << channelType);
1366 NS_LOG_DEBUG("CCA busy for " << channelType << " during " << duration.As(Time::S));
1367 m_state->SwitchMaybeToCcaBusy(duration, channelType, {});
1368}
1369
1370uint64_t
1372{
1373 NS_LOG_FUNCTION(this);
1374 return m_globalPpduUid++;
1375}
1376
1377Time
1379{
1380 return Seconds(0);
1381}
1382
1383void
1384PhyEntity::NotifyPayloadBegin(const WifiTxVector& txVector, const Time& payloadDuration)
1385{
1386 m_wifiPhy->m_phyRxPayloadBeginTrace(txVector, payloadDuration);
1387}
1388
1389void
1391{
1392 NS_LOG_FUNCTION(this << ppdu);
1393 auto txPower = m_wifiPhy->GetTxPowerForTransmission(ppdu) + m_wifiPhy->GetTxGain();
1394 auto txVector = ppdu->GetTxVector();
1395 auto txPowerSpectrum = GetTxPowerSpectralDensity(DbmToW(txPower), ppdu);
1396 Transmit(ppdu->GetTxDuration(), ppdu, txPower, txPowerSpectrum, "transmission");
1397}
1398
1399void
1402 dBm_u txPower,
1403 Ptr<SpectrumValue> txPowerSpectrum,
1404 const std::string& type)
1405{
1406 NS_LOG_FUNCTION(this << txDuration << ppdu << txPower << type);
1407 NS_LOG_DEBUG("Start " << type << ": signal power before antenna gain=" << txPower << "dBm");
1408 auto txParams = Create<WifiSpectrumSignalParameters>();
1409 txParams->duration = txDuration;
1410 txParams->psd = txPowerSpectrum;
1411 txParams->ppdu = ppdu;
1412 NS_LOG_DEBUG("Starting " << type << " with power " << txPower << " dBm on channel "
1413 << +m_wifiPhy->GetChannelNumber() << " for "
1414 << txParams->duration.As(Time::MS));
1415 NS_LOG_DEBUG("Starting " << type << " with integrated spectrum power "
1416 << WToDbm(Integral(*txPowerSpectrum)) << " dBm; spectrum model Uid: "
1417 << txPowerSpectrum->GetSpectrumModel()->GetUid());
1418 auto spectrumWifiPhy = DynamicCast<SpectrumWifiPhy>(m_wifiPhy);
1419 NS_ASSERT(spectrumWifiPhy);
1420 spectrumWifiPhy->Transmit(txParams);
1421}
1422
1423MHz_u
1424PhyEntity::GetGuardBandwidth(MHz_u currentChannelWidth) const
1425{
1426 return m_wifiPhy->GetGuardBandwidth(currentChannelWidth);
1427}
1428
1429std::tuple<dBr_u, dBr_u, dBr_u>
1434
1435Time
1437 const WifiTxVector& txVector,
1438 WifiPhyBand band) const
1439{
1440 NS_ASSERT(psduMap.size() == 1);
1441 const auto& it = psduMap.begin();
1442 return WifiPhy::CalculateTxDuration(it->second->GetSize(), txVector, band, it->first);
1443}
1444
1445bool
1447{
1448 // The PHY shall not issue a PHY-RXSTART.indication primitive in response to a PPDU that does
1449 // not overlap the primary channel
1450 const auto channelWidth = m_wifiPhy->GetChannelWidth();
1451 const auto primaryWidth = ((static_cast<uint16_t>(channelWidth) % 20 == 0)
1452 ? MHz_u{20}
1453 : channelWidth); // if the channel width is a multiple of 20 MHz,
1454 // then we consider the primary20 channel
1455 const auto p20CenterFreq =
1457 const auto p20MinFreq = p20CenterFreq - (primaryWidth / 2);
1458 const auto p20MaxFreq = p20CenterFreq + (primaryWidth / 2);
1459 const auto txChannelWidth = (ppdu->GetTxChannelWidth() / ppdu->GetTxCenterFreqs().size());
1460 for (auto txCenterFreq : ppdu->GetTxCenterFreqs())
1461 {
1462 const auto minTxFreq = txCenterFreq - txChannelWidth / 2;
1463 const auto maxTxFreq = txCenterFreq + txChannelWidth / 2;
1464 if ((p20MinFreq >= minTxFreq) && (p20MaxFreq <= maxTxFreq))
1465 {
1466 return true;
1467 }
1468 }
1469 return false;
1470}
1471
1474{
1475 return ppdu;
1476}
1477
1478} // namespace ns3
Class for representing data rates.
Definition data-rate.h:78
Time CalculateBytesTxTime(uint32_t bytes) const
Calculate transmission time.
Definition data-rate.cc:220
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
bool IsExpired() const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition event-id.cc:58
void NotifyPayloadBegin(const WifiTxVector &txVector, const Time &payloadDuration)
Fire the trace indicating that the PHY is starting to receive the payload of a PPDU.
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.
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...
std::list< WifiMode >::const_iterator end() const
Return a const iterator to past-the-last WifiMode.
void EndOfMpdu(Ptr< Event > event, Ptr< WifiMpdu > mpdu, size_t mpduIndex, Time relativeStart, Time mpduDuration)
The last symbol of an MPDU in an A-MPDU has arrived.
MHz_u GetGuardBandwidth(MHz_u currentChannelWidth) const
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.
virtual PhyFieldRxStatus DoEndReceivePreamble(Ptr< Event > event)
End receiving the preamble, perform amendment-specific actions, and provide the status of the recepti...
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper of the WifiPhy (to make it reachable for child classes)
Definition phy-entity.h:942
virtual void RxPayloadFailed(Ptr< const WifiPsdu > psdu, double snr, const WifiTxVector &txVector)
Perform amendment-specific actions when the payload is unsuccessfuly received.
void EndPreambleDetectionPeriod(Ptr< Event > event)
End the preamble detection period.
virtual void NotifyCcaBusy(const Ptr< const WifiPpdu > ppdu, Time duration, WifiChannelListType channelType)
Notify PHY state helper to switch to CCA busy state,.
virtual Ptr< WifiPpdu > BuildPpdu(const WifiConstPsduMap &psdus, const WifiTxVector &txVector, Time ppduDuration)
Build amendment-specific PPDU.
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...
virtual uint64_t ObtainNextUid(const WifiTxVector &txVector)
Obtain the next UID for the PPDU to transmit.
virtual Time DoStartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
virtual void StartReceivePreamble(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW, Time rxDuration)
Start receiving the PHY preamble of a PPDU (i.e.
virtual std::optional< Time > GetTimeToPreambleDetectionEnd() const
Get the remaining time to preamble detection period to elapse, if preamble detection is ongoing.
virtual bool HandlesMcsModes() const
Check if the WifiModes handled by this PHY are MCSs.
void Transmit(Time txDuration, Ptr< const WifiPpdu > ppdu, dBm_u txPower, Ptr< SpectrumValue > txPowerSpectrum, const std::string &type)
This function prepares most of the WifiSpectrumSignalParameters parameters and invokes SpectrumWifiPh...
const std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents() const
Get the map of current preamble events (stored in WifiPhy).
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:964
Watt_u GetRxPowerForPpdu(Ptr< Event > event) const
Obtain the received power for a given band.
Ptr< WifiPhy > m_wifiPhy
Pointer to the owning WifiPhy.
Definition phy-entity.h:941
std::pair< bool, SignalNoiseDbm > GetReceptionStatus(Ptr< WifiMpdu > mpdu, Ptr< Event > event, uint16_t staId, Time relativeMpduStart, Time mpduDuration)
Get the reception status for the provided MPDU and notify.
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:926
std::vector< EventId > m_endOfMpduEvents
the end of MPDU events (only used for A-MPDUs)
Definition phy-entity.h:948
virtual MHz_u GetRxChannelWidth(const WifiTxVector &txVector) const
Return the channel width used in the reception spectrum model.
virtual ~PhyEntity()
Destructor for PHY entity.
Definition phy-entity.cc:74
virtual const PpduFormats & GetPpduFormats() const =0
Return the PPDU formats of the PHY.
virtual uint8_t GetNumModes() const
virtual bool DoStartReceiveField(WifiPpduField field, Ptr< Event > event)
Start receiving a given field, perform amendment-specific actions, and signify if it is supported.
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition phy-entity.cc:82
std::list< WifiMode >::const_iterator begin() const
Return a const iterator to the first WifiMode.
virtual void CancelAllEvents()
Cancel and clear all running events.
virtual Time CalculateTxDuration(const WifiConstPsduMap &psduMap, const WifiTxVector &txVector, WifiPhyBand band) const
virtual void DoAbortCurrentReception(WifiPhyRxfailureReason reason)
Perform amendment-specific actions before aborting the current reception.
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Abort the current reception.
void EndReceivePayload(Ptr< Event > event)
The last symbol of the PPDU has arrived.
virtual std::pair< MHz_u, WifiSpectrumBandInfo > GetChannelWidthAndBand(const WifiTxVector &txVector, uint16_t staId) const
Get the channel width and band to use (will be overloaded by child classes).
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition phy-entity.h:967
PhyHeaderSections GetPhyHeaderSections(const WifiTxVector &txVector, Time ppduStart) const
Return a map of PHY header chunk information per PPDU field.
virtual Ptr< SpectrumValue > GetTxPowerSpectralDensity(Watt_u txPower, Ptr< const WifiPpdu > ppdu) const =0
virtual bool IsMcsSupported(uint8_t index) const
Check if the WifiMode corresponding to the given MCS index is supported.
void StartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
std::vector< EventId > m_endRxPayloadEvents
the end of receive events (only one unless UL MU reception)
Definition phy-entity.h:953
virtual void DoResetReceive(Ptr< Event > event)
Perform amendment-specific actions before resetting PHY at the end of the PPDU under reception after ...
void EndReceiveField(WifiPpduField field, Ptr< Event > event)
End receiving a given field.
virtual Ptr< Event > DoGetEvent(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW)
Get the event corresponding to the incoming PPDU.
virtual WifiMode GetSigMode(WifiPpduField field, const WifiTxVector &txVector) const
Get the WifiMode for the SIG field specified by the PPDU field.
WifiSpectrumBandInfo GetPrimaryBand(MHz_u bandWidth) const
If the operating channel width is a multiple of 20 MHz, return the info corresponding to the primary ...
WifiPpduField GetNextField(WifiPpduField currentField, WifiPreamble preamble) const
Return the field following the provided one.
void CancelRunningEndPreambleDetectionEvents()
Cancel all end preamble detection events.
Time GetDelayUntilCcaEnd(dBm_u threshold, const WifiSpectrumBandInfo &band)
Return the delay until CCA busy is ended for a given sensitivity threshold and a given band.
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Definition phy-entity.h:294
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.
Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector) const
void NotifyInterferenceRxEndAndClear(bool reset)
Notify WifiPhy's InterferenceHelper of the end of the reception, clear maps and end of MPDU event,...
void StartPreambleDetectionPeriod(Ptr< Event > event)
Start the preamble detection period.
Time GetDurationUpToField(WifiPpduField field, const WifiTxVector &txVector) const
Get the duration of the PPDU up to (but excluding) the given field.
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:961
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.
virtual void StartTx(Ptr< const WifiPpdu > ppdu)
This function is called by SpectrumWifiPhy to send the PPDU while performing amendment-specific actio...
virtual dBm_u GetCcaThreshold(const Ptr< const WifiPpdu > ppdu, WifiChannelListType channelType) const
Return the CCA threshold for a given channel type.
Time GetRemainingDurationAfterField(Ptr< const WifiPpdu > ppdu, WifiPpduField field) const
Get the remaining duration of the PPDU after the end of the given field.
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.
void StartReceiveField(WifiPpduField field, Ptr< Event > event)
Start receiving a given field.
virtual bool IsModeSupported(WifiMode mode) const
Check if the WifiMode is supported.
Definition phy-entity.cc:90
void ResetReceive(Ptr< Event > event)
Reset PHY at the end of the PPDU under reception after it has failed the PHY header.
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...
std::list< WifiMode > m_modeList
the list of supported modes
Definition phy-entity.h:945
virtual Time GetMaxDelayPpduSameUid(const WifiTxVector &txVector)
Obtain the maximum time between two PPDUs with the same UID to consider they are identical and their ...
Ptr< const Event > GetCurrentEvent() const
Get the pointer to the current event (stored in WifiPhy).
double GetRandomValue() const
Obtain a random value from the WifiPhy's generator.
std::vector< EventId > m_endPreambleDetectionEvents
the end of preamble detection events
Definition phy-entity.h:947
virtual std::optional< Time > GetTimeToMacHdrEnd(uint16_t staId) const
Get the remaining time to the end of the MAC header reception of the next MPDU being received from th...
virtual Ptr< const WifiPsdu > GetAddressedPsduInPpdu(Ptr< const WifiPpdu > ppdu) const
Get the PSDU addressed to that PHY in a PPDU (useful for MU PPDU).
SnrPer GetPhyHeaderSnrPer(WifiPpduField field, Ptr< Event > event) const
Obtain the SNR and PER of the PPDU field from the WifiPhy's InterferenceHelper class.
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 ...
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.
virtual WifiMode GetMcs(uint8_t index) const
Get the WifiMode corresponding to the given MCS index.
void AddPreambleEvent(Ptr< Event > event)
Add an entry to the map of current preamble events (stored in WifiPhy).
virtual void DoEndReceivePayload(Ptr< const WifiPpdu > ppdu)
Perform amendment-specific actions at the end of the reception of the payload.
std::tuple< dBr_u, dBr_u, dBr_u > GetTxMaskRejectionParams() const
virtual MHz_u GetMeasurementChannelWidth(const Ptr< const WifiPpdu > ppdu) const =0
Return the channel width used to measure the RSSI.
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.
virtual bool IsConfigSupported(Ptr< const WifiPpdu > ppdu) const
Checks if the signaled configuration (excluding bandwidth) is supported by the PHY.
Ptr< Event > CreateInterferenceEvent(Ptr< const WifiPpdu > ppdu, Time duration, RxPowerWattPerChannelBand &rxPower, bool isStartHePortionRxing=false)
Create an event using WifiPhy's InterferenceHelper class.
PhyRxFailureAction
Action to perform in case of RX failure.
Definition phy-entity.h:70
@ DROP
drop PPDU and set CCA_BUSY
Definition phy-entity.h:71
@ IGNORE
ignore the reception
Definition phy-entity.h:73
@ ABORT
abort reception of PPDU
Definition phy-entity.h:72
WifiSpectrumBandInfo GetSecondaryBand(MHz_u bandWidth) const
If the channel bonding is used, return the info corresponding to the secondary channel of the given b...
virtual PhyFieldRxStatus DoEndReceiveField(WifiPpduField field, Ptr< Event > event)
End receiving a given field, perform amendment-specific actions, and provide the status of the recept...
std::map< uint16_t, std::vector< EventId > > m_endOfMacHdrEvents
STA_ID-indexed map of the RX end of MAC header events.
Definition phy-entity.h:950
void ScheduleEndOfMpdus(Ptr< Event > event)
Schedule end of MPDUs events.
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition simulator.cc:206
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:403
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition nstime.h:340
@ MS
millisecond
Definition nstime.h:106
@ S
second
Definition nstime.h:105
@ NS
nanosecond
Definition nstime.h:108
bool IsZero() const
Exactly equivalent to t == 0.
Definition nstime.h:304
represent a single transmission mode
Definition wifi-mode.h:40
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:110
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper.
Definition wifi-phy.h:1346
Ptr< UniformRandomVariable > m_random
Provides uniform random variables.
Definition wifi-phy.h:1345
dB_u GetTxGain() const
Return the transmission gain.
Definition wifi-phy.cc:617
void NotifyCcaBusy(const Ptr< const WifiPpdu > ppdu, Time duration)
Notify PHY state helper to switch to CCA busy state,.
Definition wifi-phy.cc:2218
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:1516
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:1358
EventId m_endPhyRxEvent
the end of PHY receive event
Definition wifi-phy.h:1353
bool IsStateRx() const
Definition wifi-phy.cc:2163
bool m_notifyRxMacHeaderEnd
whether the PHY is capable of notifying MAC header RX end
Definition wifi-phy.h:1652
MHz_u GetFrequency() const
Definition wifi-phy.cc:1075
static Time GetPreambleDetectionDuration()
Definition wifi-phy.cc:1504
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Due to newly arrived signal, the current reception cannot be continued and has to be aborted.
Definition wifi-phy.cc:2225
Ptr< FrameCaptureModel > m_frameCaptureModel
Frame capture model.
Definition wifi-phy.h:1647
void NotifyRxBegin(Ptr< const WifiPsdu > psdu, const RxPowerWattPerChannelBand &rxPowersW)
Public method used to fire a PhyRxBegin trace.
Definition wifi-phy.cc:1640
void NotifyMonitorSniffRx(Ptr< const WifiPsdu > psdu, MHz_u channelFreq, const WifiTxVector &txVector, SignalNoiseDbm signalNoise, const 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:1683
bool IsStateOff() const
Definition wifi-phy.cc:2187
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1563
dBm_u GetCcaEdThreshold() const
Return the CCA energy detection threshold.
Definition wifi-phy.cc:541
virtual MHz_u GetGuardBandwidth(MHz_u currentChannelWidth) const =0
virtual std::tuple< dBr_u, dBr_u, dBr_u > GetTxMaskRejectionParams() const =0
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition wifi-phy.h:1381
void NotifyRxPpduDrop(Ptr< const WifiPpdu > ppdu, WifiPhyRxfailureReason reason)
Public method used to fire a PhyRxPpduDrop trace.
Definition wifi-phy.cc:1676
Ptr< ErrorModel > m_postReceptionErrorModel
Error model for receive packet events.
Definition wifi-phy.h:1650
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition wifi-phy.cc:1057
Ptr< Event > m_currentEvent
Hold the current event.
Definition wifi-phy.h:1356
uint8_t GetChannelNumber() const
Return current channel number.
Definition wifi-phy.cc:1081
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition wifi-phy.h:1361
Ptr< PreambleDetectionModel > m_preambleDetectionModel
Preamble detection model.
Definition wifi-phy.h:1648
void NotifyRxEnd(Ptr< const WifiPsdu > psdu)
Public method used to fire a PhyRxEnd trace.
Definition wifi-phy.cc:1652
MHz_u GetChannelWidth() const
Definition wifi-phy.cc:1087
bool IsStateSleep() const
Definition wifi-phy.cc:2181
virtual FrequencyRange GetCurrentFrequencyRange() const =0
Get the frequency range of the current RF interface.
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:2211
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition wifi-phy.h:1343
dBm_u GetTxPowerForTransmission(Ptr< const WifiPpdu > ppdu) const
Compute the transmit power for the next transmission.
Definition wifi-phy.cc:2298
Ptr< PhyEntity > GetPhyEntityForPpdu(const Ptr< const WifiPpdu > ppdu) const
Get the supported PHY entity to use for a received PPDU.
Definition wifi-phy.cc:789
void Reset()
Reset data upon end of TX or RX.
Definition wifi-phy.cc:1951
TracedCallback< WifiTxVector, Time > m_phyRxPayloadBeginTrace
The trace source fired when the reception of the PHY payload (PSDU) begins.
Definition wifi-phy.h:1523
Time GetLastRxEndTime() const
Return the end time of the last received packet.
Definition wifi-phy.cc:2205
TracedCallback< const WifiMacHeader &, const WifiTxVector &, Time > m_phyRxMacHeaderEndTrace
The trace source fired when the reception of a MAC header ends.
Definition wifi-phy.h:1534
Time m_timeLastPreambleDetected
Record the time the last preamble was detected.
Definition wifi-phy.h:1651
virtual WifiSpectrumBandInfo GetBand(MHz_u bandWidth, uint8_t bandIndex=0)=0
Get the info of a given band.
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition wifi-phy.cc:1069
dBm_u GetCcaSensitivityThreshold() const
Return the CCA sensitivity threshold.
Definition wifi-phy.cc:554
uint8_t GetSecondaryChannelIndex(MHz_u secondaryChannelWidth) const
If the operating channel width is made of a multiple of 20 MHz, return the index of the secondary cha...
uint8_t GetPrimaryChannelIndex(MHz_u primaryChannelWidth) const
If the operating channel width is a multiple of 20 MHz, return the index of the primary channel of th...
MHz_u GetPrimaryChannelCenterFrequency(MHz_u 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
MHz_u 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:55
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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:264
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
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.
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.
Definition wifi-types.h:47
@ PREAMBLE_DETECT_FAILURE
@ FRAME_CAPTURE_PACKET_SWITCH
@ 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.
Definition wifi-types.h:59
@ NORMAL_MPDU
The MPDU is not part of an A-MPDU.
Definition wifi-types.h:49
@ FIRST_MPDU_IN_AGGREGATE
The MPDU is the first aggregate in an A-MPDU with multiple MPDUs, but is not the last aggregate.
Definition wifi-types.h:54
@ SINGLE_MPDU
The MPDU is a single MPDU.
Definition wifi-types.h:51
@ MIDDLE_MPDU_IN_AGGREGATE
The MPDU is part of an A-MPDU with multiple MPDUs, but is neither the first nor the last aggregate.
Definition wifi-types.h:57
Every class exported by the ns3 library is enclosed in the ns3 namespace.
@ SWITCHING
The PHY layer is switching to other channel.
@ TX
The PHY layer is sending a packet.
@ OFF
The PHY layer is switched off.
@ IDLE
The PHY layer is IDLE.
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ SLEEP
The PHY layer is sleeping.
@ RX
The PHY layer is receiving a packet.
dB_u RatioToDb(double ratio)
Convert from ratio to dB.
Definition wifi-utils.cc:47
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
double Integral(const SpectrumValue &arg)
dBm_u WToDbm(Watt_u val)
Convert from Watts to dBm.
Definition wifi-utils.cc:40
double MHz_u
MHz weak type.
Definition wifi-units.h:31
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
std::map< WifiSpectrumBandInfo, Watt_u > RxPowerWattPerChannelBand
A map of the received power for each band.
Definition phy-entity.h:45
double dBm_u
dBm weak type
Definition wifi-units.h:27
double DbToRatio(dB_u val)
Convert from dB to ratio.
Definition wifi-utils.cc:28
Watt_u DbmToW(dBm_u val)
Convert from dBm to Watts.
Definition wifi-utils.cc:34
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition wifi-mode.h:24
double Watt_u
Watt weak type.
Definition wifi-units.h:25
Declaration of:
Status of the reception of the PPDU field.
Definition phy-entity.h:80
WifiPhyRxfailureReason reason
failure reason
Definition phy-entity.h:82
PhyRxFailureAction actionIfFailure
action to perform in case of failure
Definition phy-entity.h:83
bool isSuccess
outcome (true if success) of the reception
Definition phy-entity.h:81
A struct for both SNR and PER.
Definition phy-entity.h:115
double snr
SNR in linear scale.
Definition phy-entity.h:116
RxSignalInfo structure containing info on the received signal.
Definition wifi-types.h:78
double snr
SNR in linear scale.
Definition wifi-types.h:79
dBm_u rssi
RSSI.
Definition wifi-types.h:80
SignalNoiseDbm structure.
Definition wifi-types.h:64
dBm_u noise
noise power
Definition wifi-types.h:66
dBm_u signal
signal strength
Definition wifi-types.h:65
WifiSpectrumBandInfo structure containing info about a spectrum band.