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-net-device.h"
19#include "wifi-psdu.h"
22#include "wifi-utils.h"
23
24#include "ns3/assert.h"
25#include "ns3/data-rate.h"
26#include "ns3/log.h"
27#include "ns3/mobility-model.h"
28#include "ns3/packet.h"
29#include "ns3/simulator.h"
30
31#include <algorithm>
32
33#undef NS_LOG_APPEND_CONTEXT
34#define NS_LOG_APPEND_CONTEXT WIFI_PHY_NS_LOG_APPEND_CONTEXT(m_wifiPhy)
35
36namespace ns3
37{
38
39NS_LOG_COMPONENT_DEFINE("PhyEntity");
40
41std::ostream&
42operator<<(std::ostream& os, const PhyEntity::PhyRxFailureAction& action)
43{
44 switch (action)
45 {
46 case PhyEntity::DROP:
47 return (os << "DROP");
49 return (os << "ABORT");
51 return (os << "IGNORE");
52 default:
53 NS_FATAL_ERROR("Unknown action");
54 return (os << "unknown");
55 }
56}
57
58std::ostream&
59operator<<(std::ostream& os, const PhyEntity::PhyFieldRxStatus& status)
60{
61 if (status.isSuccess)
62 {
63 return os << "success";
64 }
65 else
66 {
67 return os << "failure (" << status.reason << "/" << status.actionIfFailure << ")";
68 }
69}
70
71/*******************************************************
72 * Abstract base class for PHY entities
73 *******************************************************/
74
76
83
84void
86{
87 NS_LOG_FUNCTION(this << wifiPhy);
88 m_wifiPhy = wifiPhy;
89 m_state = m_wifiPhy->m_state;
90}
91
92bool
94{
95 for (const auto& m : m_modeList)
96 {
97 if (m == mode)
98 {
99 return true;
100 }
101 }
102 return false;
103}
104
105uint8_t
107{
108 return m_modeList.size();
109}
110
112PhyEntity::GetMcs(uint8_t /* index */) const
113{
115 "This method should be used only for HtPhy and child classes. Use GetMode instead.");
116 return WifiMode();
117}
118
119bool
120PhyEntity::IsMcsSupported(uint8_t /* index */) const
121{
122 NS_ABORT_MSG("This method should be used only for HtPhy and child classes. Use IsModeSupported "
123 "instead.");
124 return false;
125}
126
127bool
129{
130 return false;
131}
132
133std::list<WifiMode>::const_iterator
135{
136 return m_modeList.begin();
137}
138
139std::list<WifiMode>::const_iterator
141{
142 return m_modeList.end();
143}
144
147{
148 NS_FATAL_ERROR("PPDU field is not a SIG field (no sense in retrieving the signaled mode) or is "
149 "unsupported: "
150 << field);
151 return WifiMode(); // should be overloaded
152}
153
156{
157 const auto& ppduFormats = GetPpduFormats();
158 const auto itPpdu = ppduFormats.find(preamble);
159 if (itPpdu != ppduFormats.end())
160 {
161 const auto itField = std::find(itPpdu->second.begin(), itPpdu->second.end(), currentField);
162 if (itField != itPpdu->second.end())
163 {
164 const auto itNextField = std::next(itField, 1);
165 if (itNextField != itPpdu->second.end())
166 {
167 return *(itNextField);
168 }
169 NS_FATAL_ERROR("No field after " << currentField << " for " << preamble
170 << " for the provided PPDU formats");
171 }
172 else
173 {
174 NS_FATAL_ERROR("Unsupported PPDU field " << currentField << " for " << preamble
175 << " for the provided PPDU formats");
176 }
177 }
178 else
179 {
180 NS_FATAL_ERROR("Unsupported preamble " << preamble << " for the provided PPDU formats");
181 }
182 return WifiPpduField::WIFI_PPDU_FIELD_PREAMBLE; // Silence compiler warning
183}
184
185Time
187{
188 if (field > WIFI_PPDU_FIELD_EHT_SIG)
189 {
190 NS_FATAL_ERROR("Unsupported PPDU field");
191 }
192 return Time(); // should be overloaded
193}
194
195Time
197{
198 Time duration;
199 for (uint8_t field = WIFI_PPDU_FIELD_PREAMBLE; field < WIFI_PPDU_FIELD_DATA; ++field)
200 {
201 duration += GetDuration(static_cast<WifiPpduField>(field), txVector);
202 }
203 return duration;
204}
205
208{
209 return WifiConstPsduMap({{SU_STA_ID, psdu}});
210}
211
214{
215 return ppdu->GetPsdu();
216}
217
219PhyEntity::GetPhyHeaderSections(const WifiTxVector& txVector, Time ppduStart) const
220{
222 WifiPpduField field = WIFI_PPDU_FIELD_PREAMBLE; // preamble always present
223 Time start = ppduStart;
224
225 while (field != WIFI_PPDU_FIELD_DATA)
226 {
227 Time duration = GetDuration(field, txVector);
228 map[field] = {{start, start + duration}, GetSigMode(field, txVector)};
229 // Move to next field
230 start += duration;
231 field = GetNextField(field, txVector.GetPreambleType());
232 }
233 return map;
234}
235
237PhyEntity::BuildPpdu(const WifiConstPsduMap& psdus, const WifiTxVector& txVector, Time ppduDuration)
238{
239 NS_LOG_FUNCTION(this << psdus << txVector << ppduDuration);
240 NS_FATAL_ERROR("This method is unsupported for the base PhyEntity class. Use the overloaded "
241 "version in the amendment-specific subclasses instead!");
242 return Create<WifiPpdu>(psdus.begin()->second,
243 txVector,
244 m_wifiPhy->GetOperatingChannel()); // should be overloaded
245}
246
247Time
249{
250 if (field ==
251 WIFI_PPDU_FIELD_DATA) // this field is not in the map returned by GetPhyHeaderSections
252 {
254 }
255 const auto& sections = GetPhyHeaderSections(txVector, Time());
256 auto it = sections.find(field);
257 NS_ASSERT(it != sections.end());
258 const auto& startStopTimes = it->second.first;
259 return startStopTimes
260 .first; // return the start time of field relatively to the beginning of the PPDU
261}
262
263SnrPer
265{
266 const auto measurementChannelWidth = GetMeasurementChannelWidth(event->GetPpdu());
267 return m_wifiPhy->m_interference->CalculatePhyHeaderSnrPer(
268 event,
269 measurementChannelWidth,
270 GetPrimaryBand(measurementChannelWidth),
271 field);
272}
273
274void
276{
277 NS_LOG_FUNCTION(this << field << *event);
278 NS_ASSERT(m_wifiPhy); // no sense if no owner WifiPhy instance
279 NS_ASSERT(m_wifiPhy->m_endPhyRxEvent.IsExpired());
281 "Use the StartReceivePreamble method for preamble reception");
282 // Handle special cases of data reception
283 if (field == WIFI_PPDU_FIELD_DATA)
284 {
285 StartReceivePayload(event);
286 return;
287 }
288
289 bool supported = DoStartReceiveField(field, event);
290 NS_ABORT_MSG_IF(!supported,
291 "Unknown field "
292 << field << " for this PHY entity"); // TODO see what to do if not supported
293 Time duration = GetDuration(field, event->GetPpdu()->GetTxVector());
294 m_wifiPhy->m_endPhyRxEvent =
295 Simulator::Schedule(duration, &PhyEntity::EndReceiveField, this, field, event);
296 m_wifiPhy->NotifyCcaBusy(
297 event->GetPpdu(),
298 duration); // keep in CCA busy state up to reception of Data (will then switch to RX)
299}
300
301void
303{
304 NS_LOG_FUNCTION(this << field << *event);
305 NS_ASSERT(m_wifiPhy); // no sense if no owner WifiPhy instance
306 NS_ASSERT(m_wifiPhy->m_endPhyRxEvent.IsExpired());
307 PhyFieldRxStatus status = DoEndReceiveField(field, event);
308 const auto& txVector = event->GetPpdu()->GetTxVector();
309 if (status.isSuccess) // move to next field if reception succeeded
310 {
311 StartReceiveField(GetNextField(field, txVector.GetPreambleType()), event);
312 }
313 else
314 {
315 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
316 switch (status.actionIfFailure)
317 {
318 case ABORT:
319 // Abort reception, but consider medium as busy
321 if (event->GetEndTime() > (Simulator::Now() + m_state->GetDelayUntilIdle()))
322 {
323 m_wifiPhy->SwitchMaybeToCcaBusy(ppdu);
324 }
325 break;
326 case DROP:
327 // Notify drop, keep in CCA busy, and perform same processing as IGNORE case
328 if (status.reason == FILTERED)
329 {
330 // PHY-RXSTART is immediately followed by PHY-RXEND (Filtered)
331 m_wifiPhy->m_phyRxPayloadBeginTrace(
332 txVector,
333 NanoSeconds(0)); // this callback (equivalent to PHY-RXSTART primitive) is also
334 // triggered for filtered PPDUs
335 }
336 m_wifiPhy->NotifyRxPpduDrop(ppdu, status.reason);
337 m_wifiPhy->NotifyCcaBusy(ppdu, GetRemainingDurationAfterField(ppdu, field));
338 // no break
339 case IGNORE:
340 // Keep in Rx state and reset at end
341 m_endRxPayloadEvents.push_back(
344 this,
345 event));
346 break;
347 default:
348 NS_FATAL_ERROR("Unknown action in case of failure");
349 }
350 }
351}
352
353Time
355{
356 const auto& txVector = ppdu->GetTxVector();
357 return ppdu->GetTxDuration() -
358 (GetDurationUpToField(field, txVector) + GetDuration(field, txVector));
359}
360
361bool
363{
364 NS_LOG_FUNCTION(this << field << *event);
366 field != WIFI_PPDU_FIELD_DATA); // handled apart for the time being
367 const auto& ppduFormats = GetPpduFormats();
368 auto itFormat = ppduFormats.find(event->GetPpdu()->GetPreamble());
369 if (itFormat != ppduFormats.end())
370 {
371 auto itField = std::find(itFormat->second.begin(), itFormat->second.end(), field);
372 if (itField != itFormat->second.end())
373 {
374 return true; // supported field so we can start receiving
375 }
376 }
377 return false; // unsupported otherwise
378}
379
382{
383 NS_LOG_FUNCTION(this << field << *event);
384 NS_ASSERT(field != WIFI_PPDU_FIELD_DATA); // handled apart for the time being
385 if (field == WIFI_PPDU_FIELD_PREAMBLE)
386 {
387 return DoEndReceivePreamble(event);
388 }
389 return PhyFieldRxStatus(false); // failed reception by default
390}
391
392void
394 RxPowerWattPerChannelBand& rxPowersW,
395 Time rxDuration)
396{
397 // The total RX power corresponds to the maximum over all the bands
398 auto it =
399 std::max_element(rxPowersW.begin(), rxPowersW.end(), [](const auto& p1, const auto& p2) {
400 return p1.second < p2.second;
401 });
402 NS_LOG_FUNCTION(this << ppdu << it->second);
403
404 auto event = DoGetEvent(ppdu, rxPowersW);
405 if (!event)
406 {
407 // PPDU should be simply considered as interference (once it has been accounted for in
408 // InterferenceHelper)
409 return;
410 }
411
412 Time endRx = Simulator::Now() + rxDuration;
413 if (ppdu->IsTruncatedTx())
414 {
415 NS_LOG_DEBUG("Packet reception stopped because transmitter has been switched off");
416 if (endRx > (Simulator::Now() + m_state->GetDelayUntilIdle()))
417 {
418 m_wifiPhy->SwitchMaybeToCcaBusy(ppdu);
419 }
421 return;
422 }
423
424 switch (m_state->GetState())
425 {
427 NS_LOG_DEBUG("Drop packet because of channel switching");
428 /*
429 * Packets received on the upcoming channel are added to the event list
430 * during the switching state. This way the medium can be correctly sensed
431 * when the device listens to the channel for the first time after the
432 * switching e.g. after channel switching, the channel may be sensed as
433 * busy due to other devices' transmissions started before the end of
434 * the switching.
435 */
437 break;
438 case WifiPhyState::RX:
439 if (m_wifiPhy->m_frameCaptureModel &&
440 m_wifiPhy->m_frameCaptureModel->IsInCaptureWindow(
441 m_wifiPhy->m_timeLastPreambleDetected) &&
442 m_wifiPhy->m_frameCaptureModel->CaptureNewFrame(m_wifiPhy->m_currentEvent, event))
443 {
445 NS_LOG_DEBUG("Switch to new packet");
447 }
448 else
449 {
450 NS_LOG_DEBUG("Drop packet because already in Rx");
451 DropPreambleEvent(ppdu, RXING, endRx);
452 if (!m_wifiPhy->m_currentEvent)
453 {
454 /*
455 * We are here because the non-legacy PHY header has not been successfully received.
456 * The PHY is kept in RX state for the duration of the PPDU, but EndReceive function
457 * is not called when the reception of the PPDU is finished, which is responsible to
458 * clear m_currentPreambleEvents. As a result, m_currentPreambleEvents should be
459 * cleared here.
460 */
461 m_wifiPhy->m_currentPreambleEvents.clear();
462 }
463 }
464 break;
465 case WifiPhyState::TX:
466 NS_LOG_DEBUG("Drop packet because already in Tx");
467 DropPreambleEvent(ppdu, TXING, endRx);
468 break;
470 if (m_wifiPhy->m_currentEvent)
471 {
472 if (m_wifiPhy->m_frameCaptureModel &&
473 m_wifiPhy->m_frameCaptureModel->IsInCaptureWindow(
474 m_wifiPhy->m_timeLastPreambleDetected) &&
475 m_wifiPhy->m_frameCaptureModel->CaptureNewFrame(m_wifiPhy->m_currentEvent, event))
476 {
478 NS_LOG_DEBUG("Switch to new packet");
480 }
481 else
482 {
483 NS_LOG_DEBUG("Drop packet because already decoding preamble");
485 }
486 }
487 else
488 {
490 }
491 break;
493 NS_ASSERT(!m_wifiPhy->m_currentEvent);
495 break;
497 NS_LOG_DEBUG("Drop packet because in sleep mode");
498 DropPreambleEvent(ppdu, SLEEPING, endRx);
499 break;
501 NS_LOG_DEBUG("Drop packet because in switched off");
503 break;
504 default:
505 NS_FATAL_ERROR("Invalid WifiPhy state.");
506 break;
507 }
508}
509
510void
512{
513 NS_LOG_FUNCTION(this << ppdu << reason << endRx);
514 m_wifiPhy->NotifyRxPpduDrop(ppdu, reason);
515 auto it = m_wifiPhy->m_currentPreambleEvents.find({ppdu->GetUid(), ppdu->GetPreamble()});
516 if (it != m_wifiPhy->m_currentPreambleEvents.end())
517 {
518 m_wifiPhy->m_currentPreambleEvents.erase(it);
519 }
520 if (!m_wifiPhy->IsStateSleep() && !m_wifiPhy->IsStateOff() &&
521 (endRx > (Simulator::Now() + m_state->GetDelayUntilIdle())))
522 {
523 // that PPDU will be noise _after_ the end of the current event.
524 m_wifiPhy->SwitchMaybeToCcaBusy(ppdu);
525 }
526}
527
528void
530{
531 NS_LOG_FUNCTION(this << ppdu << rxDuration);
532 auto it = m_wifiPhy->m_currentPreambleEvents.find({ppdu->GetUid(), ppdu->GetPreamble()});
533 if (it != m_wifiPhy->m_currentPreambleEvents.end())
534 {
535 m_wifiPhy->m_currentPreambleEvents.erase(it);
536 }
537 if (m_wifiPhy->m_currentPreambleEvents.empty())
538 {
539 m_wifiPhy->Reset();
540 }
541
542 if (rxDuration > m_state->GetDelayUntilIdle())
543 {
544 // this PPDU will be noise _after_ the completion of the current event
545 m_wifiPhy->SwitchMaybeToCcaBusy(ppdu);
546 }
547}
548
549uint16_t
551{
552 return SU_STA_ID;
553}
554
555void
557{
558 NS_LOG_FUNCTION(this << *event);
559 NS_ASSERT(m_wifiPhy->m_endPhyRxEvent.IsExpired());
560
561 Time payloadDuration = DoStartReceivePayload(event);
562 m_state->SwitchToRx(payloadDuration);
563}
564
565Time
567{
568 NS_LOG_FUNCTION(this << *event);
569 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
570 NS_LOG_DEBUG("Receiving PSDU");
571 uint16_t staId = GetStaId(ppdu);
572 m_signalNoiseMap.insert({{ppdu->GetUid(), staId}, SignalNoiseDbm()});
573 m_statusPerMpduMap.insert({{ppdu->GetUid(), staId}, std::vector<bool>()});
574 ScheduleEndOfMpdus(event);
575 const auto& txVector = event->GetPpdu()->GetTxVector();
576 Time payloadDuration = ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector);
577 m_wifiPhy->m_phyRxPayloadBeginTrace(
578 txVector,
579 payloadDuration); // this callback (equivalent to PHY-RXSTART primitive) is triggered only
580 // if headers have been correctly decoded and that the mode within is
581 // supported
582 m_endRxPayloadEvents.push_back(
583 Simulator::Schedule(payloadDuration, &PhyEntity::EndReceivePayload, this, event));
584 return payloadDuration;
585}
586
587void
589{
590 NS_LOG_FUNCTION(this << *event);
591 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
593 const auto& txVector = event->GetPpdu()->GetTxVector();
594 uint16_t staId = GetStaId(ppdu);
595 Time endOfMpduDuration;
596 Time relativeStart;
597 Time psduDuration = ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector);
598 Time remainingAmpduDuration = psduDuration;
599 size_t nMpdus = psdu->GetNMpdus();
600 MpduType mpduType =
601 (nMpdus > 1) ? FIRST_MPDU_IN_AGGREGATE : (psdu->IsSingle() ? SINGLE_MPDU : NORMAL_MPDU);
602 uint32_t totalAmpduSize = 0;
603 double totalAmpduNumSymbols = 0.0;
604 auto mpdu = psdu->begin();
605 for (size_t i = 0; i < nMpdus && mpdu != psdu->end(); ++mpdu)
606 {
607 if (m_wifiPhy->m_notifyRxMacHeaderEnd)
608 {
609 // calculate MAC header size (including A-MPDU subframe header, if present)
610 auto macHdrSize =
611 (*mpdu)->GetHeader().GetSerializedSize() + (mpduType == NORMAL_MPDU ? 0 : 4);
612 // calculate the (approximate) duration of the MAC header TX
613 auto macHdrDuration = DataRate(txVector.GetMode(staId).GetDataRate(txVector, staId))
614 .CalculateBytesTxTime(macHdrSize);
615 const auto widthBand = GetChannelWidthAndBand(txVector, staId);
616 const auto snrPer = m_wifiPhy->m_interference->CalculatePayloadSnrPer(
617 event,
618 widthBand.first,
619 widthBand.second,
620 staId,
621 {relativeStart, relativeStart + macHdrDuration});
622 if (GetRandomValue() > snrPer.per)
623 {
624 // interference level should permit to correctly decode the MAC header
625 m_endOfMacHdrEvents[staId].push_back(
626 Simulator::Schedule(endOfMpduDuration + macHdrDuration, [=, this]() {
627 m_wifiPhy->m_phyRxMacHeaderEndTrace((*mpdu)->GetHeader(),
628 txVector,
629 remainingAmpduDuration -
630 macHdrDuration);
631 }));
632 }
633 }
634
635 uint32_t size = (mpduType == NORMAL_MPDU) ? psdu->GetSize() : psdu->GetAmpduSubframeSize(i);
636 Time mpduDuration = WifiPhy::GetPayloadDuration(size,
637 txVector,
638 m_wifiPhy->GetPhyBand(),
639 mpduType,
640 true,
641 totalAmpduSize,
642 totalAmpduNumSymbols,
643 staId);
644
645 remainingAmpduDuration -= mpduDuration;
646 if (i == (nMpdus - 1) && !remainingAmpduDuration.IsZero()) // no more MPDUs coming
647 {
648 if (remainingAmpduDuration < txVector.GetGuardInterval()) // enables to ignore padding
649 {
650 mpduDuration += remainingAmpduDuration; // apply a correction just in case rounding
651 // had induced slight shift
652 }
653 }
654
655 endOfMpduDuration += mpduDuration;
656 NS_LOG_INFO("Schedule end of MPDU #"
657 << i << " in " << endOfMpduDuration.As(Time::NS) << " (relativeStart="
658 << relativeStart.As(Time::NS) << ", mpduDuration=" << mpduDuration.As(Time::NS)
659 << ", remainingAmdpuDuration=" << remainingAmpduDuration.As(Time::NS) << ")");
660 m_endOfMpduEvents.push_back(Simulator::Schedule(endOfMpduDuration,
662 this,
663 event,
664 *mpdu,
665 i,
666 relativeStart,
667 mpduDuration));
668
669 // Prepare next iteration
670 ++i;
671 relativeStart += mpduDuration;
672 mpduType = (i == (nMpdus - 1)) ? LAST_MPDU_IN_AGGREGATE : MIDDLE_MPDU_IN_AGGREGATE;
673 }
674}
675
676void
678 Ptr<WifiMpdu> mpdu,
679 size_t mpduIndex,
680 Time relativeStart,
681 Time mpduDuration)
682{
683 NS_LOG_FUNCTION(this << *event << mpduIndex << relativeStart << mpduDuration);
684 const auto ppdu = event->GetPpdu();
685 const auto& txVector = ppdu->GetTxVector();
686 uint16_t staId = GetStaId(ppdu);
687
688 std::pair<bool, SignalNoiseDbm> rxInfo =
689 GetReceptionStatus(mpdu, event, staId, relativeStart, mpduDuration);
690 NS_LOG_DEBUG("Extracted MPDU #" << mpduIndex << ": duration: " << mpduDuration.As(Time::NS)
691 << ", correct reception: " << rxInfo.first << ", Signal/Noise: "
692 << rxInfo.second.signal << "/" << rxInfo.second.noise << "dBm");
693
694 auto signalNoiseIt = m_signalNoiseMap.find({ppdu->GetUid(), staId});
695 NS_ASSERT(signalNoiseIt != m_signalNoiseMap.end());
696 signalNoiseIt->second = rxInfo.second;
697
698 RxSignalInfo rxSignalInfo;
699 rxSignalInfo.snr = DbToRatio(dB_u{rxInfo.second.signal - rxInfo.second.noise});
700 rxSignalInfo.rssi = rxInfo.second.signal;
701
702 auto statusPerMpduIt = m_statusPerMpduMap.find({ppdu->GetUid(), staId});
703 NS_ASSERT(statusPerMpduIt != m_statusPerMpduMap.end());
704 statusPerMpduIt->second.push_back(rxInfo.first);
705
706 if (rxInfo.first && GetAddressedPsduInPpdu(ppdu)->GetNMpdus() > 1)
707 {
708 // only done for correct MPDU that is part of an A-MPDU
709 m_state->NotifyRxMpdu(Create<const WifiPsdu>(mpdu, false), rxSignalInfo, txVector);
710 }
711}
712
713void
715{
716 const auto ppdu = event->GetPpdu();
717 const auto& txVector = ppdu->GetTxVector();
719 this << *event << ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector));
720 NS_ASSERT(event->GetEndTime() == Simulator::Now());
721 const auto staId = GetStaId(ppdu);
722 const auto channelWidthAndBand = GetChannelWidthAndBand(txVector, staId);
723 const auto snr = m_wifiPhy->m_interference->CalculateSnr(event,
724 channelWidthAndBand.first,
725 txVector.GetNss(staId),
726 channelWidthAndBand.second);
727
729 m_wifiPhy->NotifyRxEnd(psdu);
730
731 auto signalNoiseIt = m_signalNoiseMap.find({ppdu->GetUid(), staId});
732 NS_ASSERT(signalNoiseIt != m_signalNoiseMap.end());
733 auto statusPerMpduIt = m_statusPerMpduMap.find({ppdu->GetUid(), staId});
734 NS_ASSERT(statusPerMpduIt != m_statusPerMpduMap.end());
735 // store per-MPDU status, which is cleared by the call to DoEndReceivePayload below
736 auto statusPerMpdu = statusPerMpduIt->second;
737
738 RxSignalInfo rxSignalInfo;
739 bool success;
740
741 if (std::count(statusPerMpdu.cbegin(), statusPerMpdu.cend(), true))
742 {
743 // At least one MPDU has been successfully received
744 m_wifiPhy->NotifyMonitorSniffRx(psdu,
745 m_wifiPhy->GetFrequency(),
746 txVector,
747 signalNoiseIt->second,
748 statusPerMpdu,
749 staId);
750 rxSignalInfo.snr = snr;
751 rxSignalInfo.rssi = signalNoiseIt->second.signal; // same information for all MPDUs
752 RxPayloadSucceeded(psdu, rxSignalInfo, txVector, staId, statusPerMpdu);
753 m_wifiPhy->m_previouslyRxPpduUid =
754 ppdu->GetUid(); // store UID only if reception is successful (because otherwise trigger
755 // won't be read by MAC layer)
756 success = true;
757 }
758 else
759 {
760 RxPayloadFailed(psdu, snr, txVector);
761 success = false;
762 }
763
764 m_state->NotifyRxPpduOutcome(ppdu, rxSignalInfo, txVector, staId, statusPerMpduIt->second);
766 m_wifiPhy->SwitchMaybeToCcaBusy(ppdu);
767
768 // notify the MAC through the PHY state helper as the last action. Indeed, the notification
769 // of the RX end may lead the MAC to request a PHY state change (e.g., channel switch, sleep).
770 // Hence, all actions the PHY has to perform when RX ends should be completed before
771 // notifying the MAC.
772 success ? m_state->NotifyRxPsduSucceeded(psdu, rxSignalInfo, txVector, staId, statusPerMpdu)
773 : m_state->NotifyRxPsduFailed(psdu, snr);
774}
775
776void
778 RxSignalInfo rxSignalInfo,
779 const WifiTxVector& txVector,
780 uint16_t staId,
781 const std::vector<bool>& statusPerMpdu)
782{
783 NS_LOG_FUNCTION(this << *psdu << txVector);
784 m_state->SwitchFromRxEndOk();
785}
786
787void
789{
790 NS_LOG_FUNCTION(this << *psdu << txVector << snr);
791 m_state->SwitchFromRxEndError(txVector);
792}
793
794void
796{
797 NS_LOG_FUNCTION(this << ppdu);
798 NS_ASSERT(m_wifiPhy->GetLastRxEndTime() == Simulator::Now());
799 NotifyInterferenceRxEndAndClear(false); // don't reset WifiPhy
800
801 m_wifiPhy->m_currentEvent = nullptr;
802 m_wifiPhy->m_currentPreambleEvents.clear();
803 m_endRxPayloadEvents.clear();
804}
805
806std::pair<bool, SignalNoiseDbm>
808 Ptr<Event> event,
809 uint16_t staId,
810 Time relativeMpduStart,
811 Time mpduDuration)
812{
813 NS_LOG_FUNCTION(this << *mpdu << *event << staId << relativeMpduStart << mpduDuration);
814 const auto channelWidthAndBand = GetChannelWidthAndBand(event->GetPpdu()->GetTxVector(), staId);
815 SnrPer snrPer = m_wifiPhy->m_interference->CalculatePayloadSnrPer(
816 event,
817 channelWidthAndBand.first,
818 channelWidthAndBand.second,
819 staId,
820 {relativeMpduStart, relativeMpduStart + mpduDuration});
821
822 WifiMode mode = event->GetPpdu()->GetTxVector().GetMode(staId);
823 NS_LOG_DEBUG("rate=" << (mode.GetDataRate(event->GetPpdu()->GetTxVector(), staId))
824 << ", SNR(dB)=" << RatioToDb(snrPer.snr) << ", PER=" << snrPer.per
825 << ", size=" << mpdu->GetSize()
826 << ", relativeStart = " << relativeMpduStart.As(Time::NS)
827 << ", duration = " << mpduDuration.As(Time::NS));
828
829 // There are two error checks: PER and receive error model check.
830 // PER check models is typical for Wi-Fi and is based on signal modulation;
831 // Receive error model is optional, if we have an error model and
832 // it indicates that the packet is corrupt, drop the packet.
833 SignalNoiseDbm signalNoise;
834 signalNoise.signal = WToDbm(event->GetRxPower(channelWidthAndBand.second));
835 signalNoise.noise = WToDbm(event->GetRxPower(channelWidthAndBand.second) / snrPer.snr);
836 if (GetRandomValue() > snrPer.per &&
837 !(m_wifiPhy->m_postReceptionErrorModel &&
838 m_wifiPhy->m_postReceptionErrorModel->IsCorrupt(mpdu->GetPacket()->Copy())))
839 {
840 NS_LOG_DEBUG("Reception succeeded: " << *mpdu);
841 return {true, signalNoise};
842 }
843 else
844 {
845 NS_LOG_DEBUG("Reception failed: " << *mpdu);
846 return {false, signalNoise};
847 }
848}
849
850std::optional<Time>
852{
854 {
855 return {};
856 }
857
858 std::optional<Time> delayUntilPreambleDetectionEnd;
859 for (const auto& endPreambleDetectionEvent : m_endPreambleDetectionEvents)
860 {
861 if (endPreambleDetectionEvent.IsPending())
862 {
863 delayUntilPreambleDetectionEnd =
864 std::max(delayUntilPreambleDetectionEnd.value_or(Time{0}),
865 Simulator::GetDelayLeft(endPreambleDetectionEvent));
866 }
867 }
868 return delayUntilPreambleDetectionEnd;
869}
870
871std::optional<Time>
872PhyEntity::GetTimeToMacHdrEnd(uint16_t staId) const
873{
874 const auto it = m_endOfMacHdrEvents.find(staId);
875
876 if (it == m_endOfMacHdrEvents.cend())
877 {
878 return std::nullopt;
879 }
880
881 for (const auto& endOfMacHdrEvent : it->second)
882 {
883 if (endOfMacHdrEvent.IsPending())
884 {
885 return Simulator::GetDelayLeft(endOfMacHdrEvent);
886 }
887 }
888
889 return std::nullopt;
890}
891
892std::pair<MHz_u, WifiSpectrumBandInfo>
893PhyEntity::GetChannelWidthAndBand(const WifiTxVector& txVector, uint16_t /* staId */) const
894{
895 const auto channelWidth = GetRxChannelWidth(txVector);
896 return {channelWidth, GetPrimaryBand(channelWidth)};
897}
898
899const std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
901{
902 return m_wifiPhy->m_currentPreambleEvents;
903}
904
905void
907{
908 NS_LOG_FUNCTION(this << *event);
909 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
910 m_wifiPhy->m_currentPreambleEvents.insert({{ppdu->GetUid(), ppdu->GetPreamble()}, event});
911}
912
915{
916 // We store all incoming preamble events, and a decision is made at the end of the preamble
917 // detection window.
918 const auto& currentPreambleEvents = GetCurrentPreambleEvents();
919 const auto it = currentPreambleEvents.find({ppdu->GetUid(), ppdu->GetPreamble()});
920 if (it != currentPreambleEvents.cend())
921 {
922 // received another signal with the same content
923 NS_LOG_DEBUG("Received another PPDU for UID " << ppdu->GetUid());
924 const auto foundEvent = it->second;
925 HandleRxPpduWithSameContent(foundEvent, ppdu, rxPowersW);
926 return nullptr;
927 }
928
929 auto event = CreateInterferenceEvent(ppdu, ppdu->GetTxDuration(), rxPowersW);
930 AddPreambleEvent(event);
931 return event;
932}
933
936 Time duration,
938 bool isStartHePortionRxing /* = false */)
939{
940 return m_wifiPhy->m_interference->Add(ppdu,
941 duration,
942 rxPower,
943 m_wifiPhy->GetCurrentFrequencyRange(),
944 isStartHePortionRxing);
945}
946
947void
951{
952 if (const auto maxDelay =
953 m_wifiPhy->GetPhyEntityForPpdu(ppdu)->GetMaxDelayPpduSameUid(ppdu->GetTxVector());
954 Simulator::Now() - event->GetStartTime() > maxDelay)
955 {
956 // This PPDU arrived too late to be decoded properly. The PPDU is dropped and added as
957 // interference
958 event = CreateInterferenceEvent(ppdu, ppdu->GetTxDuration(), rxPower);
959 NS_LOG_DEBUG("Drop PPDU that arrived too late");
960 m_wifiPhy->NotifyRxPpduDrop(ppdu, PPDU_TOO_LATE);
961 return;
962 }
963
964 // Update received power and TXVECTOR of the event associated to that transmission upon
965 // reception of a signal adding up constructively (in case of a UL MU PPDU or non-HT duplicate
966 // PPDU)
967 m_wifiPhy->m_interference->UpdateEvent(event, rxPower);
968 const auto& txVector = ppdu->GetTxVector();
969 const auto& eventTxVector = event->GetPpdu()->GetTxVector();
970 auto updatedTxVector{eventTxVector};
971 updatedTxVector.SetChannelWidth(
972 std::max(eventTxVector.GetChannelWidth(), txVector.GetChannelWidth()));
973 if (updatedTxVector.GetChannelWidth() != eventTxVector.GetChannelWidth())
974 {
975 event->UpdatePpdu(ppdu);
976 }
977}
978
979void
981{
982 m_wifiPhy->m_interference->NotifyRxEnd(Simulator::Now(), m_wifiPhy->GetCurrentFrequencyRange());
983 m_signalNoiseMap.clear();
984 m_statusPerMpduMap.clear();
985 for (const auto& endOfMpduEvent : m_endOfMpduEvents)
986 {
987 NS_ASSERT(endOfMpduEvent.IsExpired());
988 }
989 m_endOfMpduEvents.clear();
990 for (const auto& [staId, endOfMacHdrEvents] : m_endOfMacHdrEvents)
991 {
992 for (const auto& endOfMacHdrEvent : endOfMacHdrEvents)
993 {
994 NS_ASSERT(endOfMacHdrEvent.IsExpired());
995 }
996 }
997 m_endOfMacHdrEvents.clear();
998 if (reset)
999 {
1000 m_wifiPhy->Reset();
1001 }
1002}
1003
1006{
1007 NS_LOG_FUNCTION(this << *event);
1008 NS_ASSERT(m_wifiPhy->m_currentPreambleEvents.size() ==
1009 1); // Synched on one after detection period
1010 return PhyFieldRxStatus(true); // always consider that preamble has been correctly received if
1011 // preamble detection was OK
1012}
1013
1014void
1016{
1017 NS_LOG_FUNCTION(this << *event);
1018 const auto rxPower = GetRxPowerForPpdu(event);
1019 NS_LOG_DEBUG("Sync to signal (power=" << (rxPower > Watt_u{0.0}
1020 ? std::to_string(WToDbm(rxPower)) + "dBm)"
1021 : std::to_string(rxPower) + "W)"));
1022 m_wifiPhy->m_interference->NotifyRxStart(
1023 m_wifiPhy->GetCurrentFrequencyRange()); // We need to notify it now so that it starts
1024 // recording events
1028 this,
1029 event));
1030}
1031
1032void
1034{
1035 NS_LOG_FUNCTION(this << *event);
1036 NS_ASSERT(!m_wifiPhy->IsStateRx());
1037 NS_ASSERT(m_wifiPhy->m_endPhyRxEvent.IsExpired()); // since end of preamble reception is
1038 // scheduled by this method upon success
1039
1040 // calculate PER on the measurement channel for PHY headers
1041 const auto measurementChannelWidth = GetMeasurementChannelWidth(event->GetPpdu());
1042 auto measurementBand = GetPrimaryBand(measurementChannelWidth);
1043 std::optional<Watt_u>
1044 maxRxPower; // in case current event may not be sent on measurement channel
1045 Ptr<Event> maxEvent;
1046 NS_ASSERT(!m_wifiPhy->m_currentPreambleEvents.empty());
1047 for (auto preambleEvent : m_wifiPhy->m_currentPreambleEvents)
1048 {
1049 const auto rxPower = preambleEvent.second->GetRxPower(measurementBand);
1050 if (!maxRxPower || (rxPower > *maxRxPower))
1051 {
1052 maxRxPower = rxPower;
1053 maxEvent = preambleEvent.second;
1054 }
1055 }
1056
1057 NS_ASSERT(maxEvent);
1058 if (maxEvent != event)
1059 {
1060 NS_LOG_DEBUG("Receiver got a stronger packet with UID "
1061 << maxEvent->GetPpdu()->GetUid()
1062 << " during preamble detection: drop packet with UID "
1063 << event->GetPpdu()->GetUid());
1064 m_wifiPhy->NotifyRxPpduDrop(event->GetPpdu(), BUSY_DECODING_PREAMBLE);
1065
1066 auto it = m_wifiPhy->m_currentPreambleEvents.find(
1067 {event->GetPpdu()->GetUid(), event->GetPpdu()->GetPreamble()});
1068 m_wifiPhy->m_currentPreambleEvents.erase(it);
1069 // This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to
1070 // the power at the start of the PPDU
1071 m_wifiPhy->m_interference->NotifyRxEnd(maxEvent->GetStartTime(),
1072 m_wifiPhy->GetCurrentFrequencyRange());
1073 // Make sure InterferenceHelper keeps recording events
1074 m_wifiPhy->m_interference->NotifyRxStart(m_wifiPhy->GetCurrentFrequencyRange());
1075 return;
1076 }
1077
1078 m_wifiPhy->m_currentEvent = event;
1079
1080 const auto snr = m_wifiPhy->m_interference->CalculateSnr(m_wifiPhy->m_currentEvent,
1081 measurementChannelWidth,
1082 1,
1083 measurementBand);
1084 NS_LOG_DEBUG("SNR(dB)=" << RatioToDb(snr) << " at end of preamble detection period");
1085
1086 if (const auto power = m_wifiPhy->m_currentEvent->GetRxPower(measurementBand);
1087 (!m_wifiPhy->m_preambleDetectionModel && maxRxPower && (*maxRxPower > Watt_u{0.0})) ||
1088 (m_wifiPhy->m_preambleDetectionModel && power > Watt_u{0.0} &&
1089 m_wifiPhy->m_preambleDetectionModel->IsPreambleDetected(WToDbm(power),
1090 snr,
1091 measurementChannelWidth)))
1092 {
1093 // A bit convoluted but it enables to sync all PHYs
1094 for (auto& it : m_wifiPhy->m_phyEntities)
1095 {
1096 it.second->CancelRunningEndPreambleDetectionEvents();
1097 }
1098
1099 for (auto it = m_wifiPhy->m_currentPreambleEvents.begin();
1100 it != m_wifiPhy->m_currentPreambleEvents.end();)
1101 {
1102 if (it->second != m_wifiPhy->m_currentEvent)
1103 {
1104 NS_LOG_DEBUG("Drop packet with UID " << it->first.first << " and preamble "
1105 << it->first.second << " arrived at time "
1106 << it->second->GetStartTime());
1108 if (m_wifiPhy->m_currentEvent->GetPpdu()->GetUid() > it->first.first)
1109 {
1111 // This is needed to cleanup the m_firstPowerPerBand so that the first power
1112 // corresponds to the power at the start of the PPDU
1113 m_wifiPhy->m_interference->NotifyRxEnd(
1114 m_wifiPhy->m_currentEvent->GetStartTime(),
1115 m_wifiPhy->GetCurrentFrequencyRange());
1116 }
1117 else
1118 {
1119 reason = BUSY_DECODING_PREAMBLE;
1120 }
1121 m_wifiPhy->NotifyRxPpduDrop(it->second->GetPpdu(), reason);
1122
1123 it = m_wifiPhy->m_currentPreambleEvents.erase(it);
1124 }
1125 else
1126 {
1127 ++it;
1128 }
1129 }
1130
1131 // Make sure InterferenceHelper keeps recording events
1132 m_wifiPhy->m_interference->NotifyRxStart(m_wifiPhy->GetCurrentFrequencyRange());
1133
1134 m_wifiPhy->NotifyRxBegin(GetAddressedPsduInPpdu(m_wifiPhy->m_currentEvent->GetPpdu()),
1135 m_wifiPhy->m_currentEvent->GetRxPowerPerBand());
1136 m_wifiPhy->m_timeLastPreambleDetected = Simulator::Now();
1137
1138 // Continue receiving preamble
1139 const auto durationTillEnd =
1140 GetDuration(WIFI_PPDU_FIELD_PREAMBLE, event->GetPpdu()->GetTxVector()) -
1142 m_wifiPhy->NotifyCcaBusy(event->GetPpdu(),
1143 durationTillEnd); // will be prolonged by next field
1144 m_wifiPhy->m_endPhyRxEvent = Simulator::Schedule(durationTillEnd,
1146 this,
1148 event);
1149 }
1150 else
1151 {
1152 NS_LOG_DEBUG("Drop packet because PHY preamble detection failed");
1153 // Like CCA-SD, CCA-ED is governed by the 4 us CCA window to flag CCA-BUSY
1154 // for any received signal greater than the CCA-ED threshold.
1155 DropPreambleEvent(m_wifiPhy->m_currentEvent->GetPpdu(),
1157 m_wifiPhy->m_currentEvent->GetEndTime());
1158 if (m_wifiPhy->m_currentPreambleEvents.empty())
1159 {
1160 // Do not erase events if there are still pending preamble events to be processed
1161 m_wifiPhy->m_interference->NotifyRxEnd(Simulator::Now(),
1162 m_wifiPhy->GetCurrentFrequencyRange());
1163 }
1164 m_wifiPhy->m_currentEvent = nullptr;
1165 // Cancel preamble reception
1166 m_wifiPhy->m_endPhyRxEvent.Cancel();
1167 }
1168}
1169
1170bool
1172{
1173 WifiMode txMode = ppdu->GetTxVector().GetMode();
1174 if (!IsModeSupported(txMode))
1175 {
1176 NS_LOG_DEBUG("Drop packet because it was sent using an unsupported mode (" << txMode
1177 << ")");
1178 return false;
1179 }
1180 return true;
1181}
1182
1183void
1185{
1186 NS_LOG_FUNCTION(this);
1188 for (auto& endRxPayloadEvent : m_endRxPayloadEvents)
1189 {
1190 endRxPayloadEvent.Cancel();
1191 }
1192 m_endRxPayloadEvents.clear();
1193 for (auto& endMpduEvent : m_endOfMpduEvents)
1194 {
1195 endMpduEvent.Cancel();
1196 }
1197 m_endOfMpduEvents.clear();
1198 for (auto& [staId, endOfMacHdrEvents] : m_endOfMacHdrEvents)
1199 {
1200 for (auto& endMacHdrEvent : endOfMacHdrEvents)
1201 {
1202 endMacHdrEvent.Cancel();
1203 }
1204 }
1205 m_endOfMacHdrEvents.clear();
1206}
1207
1208void
1210{
1211 NS_LOG_FUNCTION(this);
1212 for (auto& endPreambleDetectionEvent : m_endPreambleDetectionEvents)
1213 {
1214 endPreambleDetectionEvent.Cancel();
1215 }
1217}
1218
1219void
1221{
1222 NS_LOG_FUNCTION(this << reason);
1224 m_wifiPhy->AbortCurrentReception(reason);
1225}
1226
1227void
1229{
1230 NS_LOG_FUNCTION(this << reason);
1231 if (m_wifiPhy->m_currentEvent) // Otherwise abort has already been called just before
1232 {
1233 for (auto& endMpduEvent : m_endOfMpduEvents)
1234 {
1235 endMpduEvent.Cancel();
1236 }
1237 m_endOfMpduEvents.clear();
1238 for (auto& [staId, endOfMacHdrEvents] : m_endOfMacHdrEvents)
1239 {
1240 for (auto& endMacHdrEvent : endOfMacHdrEvents)
1241 {
1242 endMacHdrEvent.Cancel();
1243 }
1244 }
1245 m_endOfMacHdrEvents.clear();
1246 }
1247}
1248
1249void
1251{
1252 NS_LOG_FUNCTION(this << *event);
1253 DoResetReceive(event);
1254 NS_ASSERT(!m_wifiPhy->IsStateRx());
1255 m_wifiPhy->m_interference->NotifyRxEnd(Simulator::Now(), m_wifiPhy->GetCurrentFrequencyRange());
1256 NS_ASSERT(m_endRxPayloadEvents.size() == 1 && m_endRxPayloadEvents.front().IsExpired());
1257 m_endRxPayloadEvents.clear();
1258 m_wifiPhy->m_currentEvent = nullptr;
1259 m_wifiPhy->m_currentPreambleEvents.clear();
1260 m_wifiPhy->SwitchMaybeToCcaBusy(event->GetPpdu());
1261}
1262
1263void
1265{
1266 NS_LOG_FUNCTION(this << *event);
1267 NS_ASSERT(event->GetEndTime() == Simulator::Now());
1268}
1269
1270double
1272{
1273 return m_wifiPhy->m_random->GetValue();
1274}
1275
1276Watt_u
1278{
1279 return event->GetRxPower(GetPrimaryBand(GetMeasurementChannelWidth(event->GetPpdu())));
1280}
1281
1284{
1285 return m_wifiPhy->m_currentEvent;
1286}
1287
1290{
1291 if (static_cast<uint16_t>(m_wifiPhy->GetChannelWidth()) % 20 != 0)
1292 {
1293 return m_wifiPhy->GetBand(bandWidth);
1294 }
1295 return m_wifiPhy->GetBand(bandWidth,
1296 m_wifiPhy->GetOperatingChannel().GetPrimaryChannelIndex(bandWidth));
1297}
1298
1301{
1302 NS_ASSERT(m_wifiPhy->GetChannelWidth() >= MHz_u{40});
1303 return m_wifiPhy->GetBand(bandWidth,
1304 m_wifiPhy->GetOperatingChannel().GetSecondaryChannelIndex(bandWidth));
1305}
1306
1307MHz_u
1309{
1310 return std::min(m_wifiPhy->GetChannelWidth(), txVector.GetChannelWidth());
1311}
1312
1313dBm_u
1315 WifiChannelListType /*channelType*/) const
1316{
1317 return (!ppdu) ? m_wifiPhy->GetCcaEdThreshold() : m_wifiPhy->GetCcaSensitivityThreshold();
1318}
1319
1320Time
1322{
1323 return m_wifiPhy->m_interference->GetEnergyDuration(DbmToW(threshold), band);
1324}
1325
1326void
1328{
1329 // We are here because we have received the first bit of a packet and we are
1330 // not going to be able to synchronize on it
1331 // In this model, CCA becomes busy when the aggregation of all signals as
1332 // tracked by the InterferenceHelper class is higher than the CcaBusyThreshold
1333 const auto ccaIndication = GetCcaIndication(ppdu);
1334 if (ccaIndication.has_value())
1335 {
1336 NS_LOG_DEBUG("CCA busy for " << ccaIndication.value().second << " during "
1337 << ccaIndication.value().first.As(Time::S));
1338 m_state->SwitchMaybeToCcaBusy(ccaIndication.value().first,
1339 ccaIndication.value().second,
1340 {});
1341 return;
1342 }
1343 if (ppdu)
1344 {
1345 SwitchMaybeToCcaBusy(nullptr);
1346 }
1347}
1348
1351{
1352 const auto channelWidth = GetMeasurementChannelWidth(ppdu);
1353 NS_LOG_FUNCTION(this << channelWidth);
1354 const auto ccaThreshold = GetCcaThreshold(ppdu, WIFI_CHANLIST_PRIMARY);
1355 const Time delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, GetPrimaryBand(channelWidth));
1356 if (delayUntilCcaEnd.IsStrictlyPositive())
1357 {
1358 return std::make_pair(delayUntilCcaEnd, WIFI_CHANLIST_PRIMARY);
1359 }
1360 return std::nullopt;
1361}
1362
1363void
1365 Time duration,
1366 WifiChannelListType channelType)
1367{
1368 NS_LOG_FUNCTION(this << duration << channelType);
1369 NS_LOG_DEBUG("CCA busy for " << channelType << " during " << duration.As(Time::S));
1370 m_state->SwitchMaybeToCcaBusy(duration, channelType, {});
1371}
1372
1373uint64_t
1375{
1376 NS_LOG_FUNCTION(this);
1377 return m_globalPpduUid++;
1378}
1379
1380Time
1382{
1383 return Seconds(0);
1384}
1385
1386void
1387PhyEntity::NotifyPayloadBegin(const WifiTxVector& txVector, const Time& payloadDuration)
1388{
1389 m_wifiPhy->m_phyRxPayloadBeginTrace(txVector, payloadDuration);
1390}
1391
1392void
1394{
1395 NS_LOG_FUNCTION(this << ppdu);
1396 auto txPower = m_wifiPhy->GetTxPowerForTransmission(ppdu) + m_wifiPhy->GetTxGain();
1397 auto txVector = ppdu->GetTxVector();
1398 auto txPowerSpectrum = GetTxPowerSpectralDensity(DbmToW(txPower), ppdu);
1399 Transmit(ppdu->GetTxDuration(), ppdu, txPower, txPowerSpectrum, "transmission");
1400}
1401
1402void
1405 dBm_u txPower,
1406 Ptr<SpectrumValue> txPowerSpectrum,
1407 const std::string& type)
1408{
1409 NS_LOG_FUNCTION(this << txDuration << ppdu << txPower << type);
1410 NS_LOG_DEBUG("Start " << type << ": signal power before antenna gain=" << txPower << "dBm");
1411 auto txParams = Create<WifiSpectrumSignalParameters>();
1412 txParams->duration = txDuration;
1413 txParams->psd = txPowerSpectrum;
1414 txParams->ppdu = ppdu;
1415 NS_LOG_DEBUG("Starting " << type << " with power " << txPower << " dBm on channel "
1416 << +m_wifiPhy->GetChannelNumber() << " for "
1417 << txParams->duration.As(Time::MS));
1418 NS_LOG_DEBUG("Starting " << type << " with integrated spectrum power "
1419 << WToDbm(Integral(*txPowerSpectrum)) << " dBm; spectrum model Uid: "
1420 << txPowerSpectrum->GetSpectrumModel()->GetUid());
1421 auto spectrumWifiPhy = DynamicCast<SpectrumWifiPhy>(m_wifiPhy);
1422 NS_ASSERT(spectrumWifiPhy);
1423 spectrumWifiPhy->Transmit(txParams);
1424}
1425
1426MHz_u
1427PhyEntity::GetGuardBandwidth(MHz_u currentChannelWidth) const
1428{
1429 return m_wifiPhy->GetGuardBandwidth(currentChannelWidth);
1430}
1431
1432std::tuple<dBr_u, dBr_u, dBr_u>
1434{
1435 return m_wifiPhy->GetTxMaskRejectionParams();
1436}
1437
1438Time
1440 const WifiTxVector& txVector,
1441 WifiPhyBand band) const
1442{
1443 NS_ASSERT(psduMap.size() == 1);
1444 const auto& it = psduMap.begin();
1445 return WifiPhy::CalculateTxDuration(it->second->GetSize(), txVector, band, it->first);
1446}
1447
1448bool
1450{
1451 // The PHY shall not issue a PHY-RXSTART.indication primitive in response to a PPDU that does
1452 // not overlap the primary channel
1453 const auto channelWidth = m_wifiPhy->GetChannelWidth();
1454 const auto primaryWidth = ((static_cast<uint16_t>(channelWidth) % 20 == 0)
1455 ? MHz_u{20}
1456 : channelWidth); // if the channel width is a multiple of 20 MHz,
1457 // then we consider the primary20 channel
1458 const auto p20CenterFreq =
1459 m_wifiPhy->GetOperatingChannel().GetPrimaryChannelCenterFrequency(primaryWidth);
1460 const auto p20MinFreq = p20CenterFreq - (primaryWidth / 2);
1461 const auto p20MaxFreq = p20CenterFreq + (primaryWidth / 2);
1462 const auto txChannelWidth = (ppdu->GetTxChannelWidth() / ppdu->GetTxCenterFreqs().size());
1463 for (auto txCenterFreq : ppdu->GetTxCenterFreqs())
1464 {
1465 const auto minTxFreq = txCenterFreq - txChannelWidth / 2;
1466 const auto maxTxFreq = txCenterFreq + txChannelWidth / 2;
1467 if ((p20MinFreq >= minTxFreq) && (p20MaxFreq <= maxTxFreq))
1468 {
1469 return true;
1470 }
1471 }
1472 return false;
1473}
1474
1477{
1478 return ppdu;
1479}
1480
1481} // 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 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:907
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:929
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:906
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:891
std::vector< EventId > m_endOfMpduEvents
the end of MPDU events (only used for A-MPDUs)
Definition phy-entity.h:913
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:77
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:85
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:932
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:918
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.
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:926
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...
SnrPer GetPhyHeaderSnrPer(WifiPpduField field, Ptr< Event > event) const
Obtain the SNR and PER of the PPDU field from the WifiPhy's InterferenceHelper class.
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:93
void ResetReceive(Ptr< Event > event)
Reset PHY at the end of the PPDU under reception after it has failed the PHY header.
PhyHeaderSections GetPhyHeaderSections(const WifiTxVector &txVector, Time ppduStart) const
Return a map of PHY header chunk information per PPDU field.
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:910
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:912
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).
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:73
@ DROP
drop PPDU and set CCA_BUSY
Definition phy-entity.h:74
@ IGNORE
ignore the reception
Definition phy-entity.h:76
@ ABORT
abort reception of PPDU
Definition phy-entity.h:75
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:915
void ScheduleEndOfMpdus(Ptr< Event > event)
Schedule end of MPDUs events.
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
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:96
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:409
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition nstime.h:342
@ MS
millisecond
Definition nstime.h:108
@ S
second
Definition nstime.h:107
@ NS
nanosecond
Definition nstime.h:110
bool IsZero() const
Exactly equivalent to t == 0.
Definition nstime.h:306
represent a single transmission mode
Definition wifi-mode.h:38
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:110
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:1517
static Time GetPreambleDetectionDuration()
Definition wifi-phy.cc:1505
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1564
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:439
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1405
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
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:48
@ 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:60
@ NORMAL_MPDU
The MPDU is not part of an A-MPDU.
Definition wifi-types.h:50
@ 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:55
@ SINGLE_MPDU
The MPDU is a single MPDU.
Definition wifi-types.h:52
@ 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:58
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::map< WifiSpectrumBandInfo, Watt_u > RxPowerWattPerChannelBand
A map of the received power for each band.
@ 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:45
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
double Integral(const SpectrumValue &arg)
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
dBm_u WToDbm(Watt_u val)
Convert from Watts to dBm.
Definition wifi-utils.cc:38
double MHz_u
MHz weak type.
Definition wifi-units.h:31
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:585
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:26
Watt_u DbmToW(dBm_u val)
Convert from dBm to Watts.
Definition wifi-utils.cc:32
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)
double Watt_u
Watt weak type.
Definition wifi-units.h:25
double dB_u
dB weak type
Definition wifi-units.h:28
Declaration of:
Status of the reception of the PPDU field.
Definition phy-entity.h:83
WifiPhyRxfailureReason reason
failure reason
Definition phy-entity.h:85
PhyRxFailureAction actionIfFailure
action to perform in case of failure
Definition phy-entity.h:86
bool isSuccess
outcome (true if success) of the reception
Definition phy-entity.h:84
RxSignalInfo structure containing info on the received signal.
Definition wifi-types.h:79
double snr
SNR in linear scale.
Definition wifi-types.h:80
dBm_u rssi
RSSI.
Definition wifi-types.h:81
SignalNoiseDbm structure.
Definition wifi-types.h:65
dBm_u noise
noise power
Definition wifi-types.h:67
dBm_u signal
signal strength
Definition wifi-types.h:66
A struct for both SNR and PER.
double snr
SNR in linear scale.
double per
PER.
WifiSpectrumBandInfo structure containing info about a spectrum band.