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