A Discrete-Event Network Simulator
API
phy-entity.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2020 Orange Labs
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Authors: Rediet <getachew.redieteab@orange.com>
19 * Sébastien Deronne <sebastien.deronne@gmail.com> (for logic ported from wifi-phy and spectrum-wifi-phy)
20 * Mathieu Lacage <mathieu.lacage@sophia.inria.fr> (for logic ported from wifi-phy)
21 */
22
23#include "phy-entity.h"
24#include "spectrum-wifi-phy.h"
25#include "wifi-psdu.h"
27#include "frame-capture-model.h"
28#include "wifi-utils.h"
30#include "ns3/packet.h"
31#include "ns3/simulator.h"
32#include "ns3/log.h"
33#include "ns3/assert.h"
34#include <algorithm>
35
36namespace ns3 {
37
38NS_LOG_COMPONENT_DEFINE ("PhyEntity");
39
40std::ostream & operator << (std::ostream &os, const PhyEntity::PhyRxFailureAction &action)
41{
42 switch (action)
43 {
44 case PhyEntity::DROP:
45 return (os << "DROP");
47 return (os << "ABORT");
49 return (os << "IGNORE");
50 default:
51 NS_FATAL_ERROR ("Unknown action");
52 return (os << "unknown");
53 }
54}
55
56std::ostream & operator << (std::ostream &os, const PhyEntity::PhyFieldRxStatus &status)
57{
58 if (status.isSuccess)
59 {
60 return os << "success";
61 }
62 else
63 {
64 return os << "failure (" << status.reason << "/" << status.actionIfFailure << ")";
65 }
66}
67
68/*******************************************************
69 * Abstract base class for PHY entities
70 *******************************************************/
71
73
75{
76 NS_LOG_FUNCTION (this);
77 m_modeList.clear ();
79}
80
81void
83{
84 NS_LOG_FUNCTION (this << wifiPhy);
85 m_wifiPhy = wifiPhy;
87}
88
89bool
91{
92 for (const auto & m : m_modeList)
93 {
94 if (m == mode)
95 {
96 return true;
97 }
98 }
99 return false;
100}
101
102uint8_t
104{
105 return m_modeList.size ();
106}
107
109PhyEntity::GetMcs (uint8_t /* index */) const
110{
111 NS_ABORT_MSG ("This method should be used only for HtPhy and child classes. Use GetMode instead.");
112 return WifiMode ();
113}
114
115bool
116PhyEntity::IsMcsSupported (uint8_t /* index */) const
117{
118 NS_ABORT_MSG ("This method should be used only for HtPhy and child classes. Use IsModeSupported instead.");
119 return false;
120}
121
122bool
124{
125 return false;
126}
127
128std::list<WifiMode>::const_iterator
130{
131 return m_modeList.begin ();
132}
133
134std::list<WifiMode>::const_iterator
135PhyEntity::end (void) const
136{
137 return m_modeList.end ();
138}
139
142{
143 NS_FATAL_ERROR ("PPDU field is not a SIG field (no sense in retrieving the signaled mode) or is unsupported: " << field);
144 return WifiMode (); //should be overloaded
145}
146
149{
150 auto ppduFormats = GetPpduFormats ();
151 const auto itPpdu = ppduFormats.find (preamble);
152 if (itPpdu != ppduFormats.end ())
153 {
154 const auto itField = std::find (itPpdu->second.begin (), itPpdu->second.end (), currentField);
155 if (itField != itPpdu->second.end ())
156 {
157 const auto itNextField = std::next (itField, 1);
158 if (itNextField != itPpdu->second.end ())
159 {
160 return *(itNextField);
161 }
162 NS_FATAL_ERROR ("No field after " << currentField << " for " << preamble << " for the provided PPDU formats");
163 }
164 else
165 {
166 NS_FATAL_ERROR ("Unsupported PPDU field " << currentField << " for " << preamble << " for the provided PPDU formats");
167 }
168 }
169 else
170 {
171 NS_FATAL_ERROR ("Unsupported preamble " << preamble << " for the provided PPDU formats");
172 }
173}
174
175Time
177{
178 if (field > WIFI_PPDU_FIELD_SIG_B)
179 {
180 NS_FATAL_ERROR ("Unsupported PPDU field");
181 }
182 return MicroSeconds (0); //should be overloaded
183}
184
185Time
187{
188 Time duration = MicroSeconds (0);
189 for (uint8_t field = WIFI_PPDU_FIELD_PREAMBLE; field < WIFI_PPDU_FIELD_DATA; ++field)
190 {
191 duration += GetDuration (static_cast<WifiPpduField> (field), txVector);
192 }
193 return duration;
194}
195
198{
199 return WifiConstPsduMap ({std::make_pair (SU_STA_ID, psdu)});
200}
201
204{
205 return ppdu->GetPsdu ();
206}
207
209PhyEntity::GetPhyHeaderSections (const WifiTxVector& txVector, Time ppduStart) const
210{
212 WifiPpduField field = WIFI_PPDU_FIELD_PREAMBLE; //preamble always present
213 Time start = ppduStart;
214
215 while (field != WIFI_PPDU_FIELD_DATA)
216 {
217 Time duration = GetDuration (field, txVector);
218 map[field] = std::make_pair (std::make_pair (start, start + duration),
219 GetSigMode (field, txVector));
220 //Move to next field
221 start += duration;
222 field = GetNextField (field, txVector.GetPreambleType ());
223 }
224 return map;
225}
226
228PhyEntity::BuildPpdu (const WifiConstPsduMap & psdus, const WifiTxVector& txVector, Time /* ppduDuration */)
229{
230 NS_LOG_FUNCTION (this << psdus << txVector);
231 NS_FATAL_ERROR ("This method is unsupported for the base PhyEntity class. Use the overloaded version in the amendment-specific subclasses instead!");
232 return Create<WifiPpdu> (psdus.begin ()->second, txVector); //should be overloaded
233}
234
235Time
237{
238 if (field == WIFI_PPDU_FIELD_DATA) //this field is not in the map returned by GetPhyHeaderSections
239 {
241 }
242 const auto & sections = GetPhyHeaderSections (txVector, NanoSeconds (0));
243 auto it = sections.find (field);
244 NS_ASSERT (it != sections.end ());
245 const auto & startStopTimes = it->second.first;
246 return startStopTimes.first; //return the start time of field relatively to the beginning of the PPDU
247}
248
251{
252 uint16_t measurementChannelWidth = GetMeasurementChannelWidth (event->GetPpdu ());
253 return m_wifiPhy->m_interference.CalculatePhyHeaderSnrPer (event, measurementChannelWidth, m_wifiPhy->GetPrimaryBand (measurementChannelWidth),
254 field);
255}
256
257void
259{
260 NS_LOG_FUNCTION (this << field << *event);
261 NS_ASSERT (m_wifiPhy); //no sense if no owner WifiPhy instance
263 NS_ABORT_MSG_IF (field == WIFI_PPDU_FIELD_PREAMBLE, "Use the StartReceivePreamble method for preamble reception");
264 //Handle special cases of data reception
265 if (field == WIFI_PPDU_FIELD_DATA)
266 {
267 StartReceivePayload (event);
268 return;
269 }
270
271 bool supported = DoStartReceiveField (field, event);
272 NS_ABORT_MSG_IF (!supported, "Unknown field " << field << " for this PHY entity"); //TODO see what to do if not supported
273 Time duration = GetDuration (field, event->GetTxVector ());
275 m_state->SwitchMaybeToCcaBusy (duration); //keep in CCA busy state up to reception of Data (will then switch to RX)
276}
277
278void
280{
281 NS_LOG_FUNCTION (this << field << *event);
282 NS_ASSERT (m_wifiPhy); //no sense if no owner WifiPhy instance
284 PhyFieldRxStatus status = DoEndReceiveField (field, event);
285 WifiTxVector txVector = event->GetTxVector ();
286 if (status.isSuccess) //move to next field if reception succeeded
287 {
288 StartReceiveField (GetNextField (field, txVector.GetPreambleType ()), event);
289 }
290 else
291 {
292 Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
293 switch (status.actionIfFailure)
294 {
295 case ABORT:
296 //Abort reception, but consider medium as busy
298 if (event->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
299 {
301 }
302 break;
303 case DROP:
304 //Notify drop, keep in CCA busy, and perform same processing as IGNORE case
305 if (status.reason == FILTERED)
306 {
307 //PHY-RXSTART is immediately followed by PHY-RXEND (Filtered)
308 m_wifiPhy->m_phyRxPayloadBeginTrace (txVector, NanoSeconds (0)); //this callback (equivalent to PHY-RXSTART primitive) is also triggered for filtered PPDUs
309 }
311 m_state->SwitchMaybeToCcaBusy (GetRemainingDurationAfterField (ppdu, field)); //keep in CCA busy state till the end
312 //no break
313 case IGNORE:
314 //Keep in Rx state and reset at end
316 &PhyEntity::ResetReceive, this, event));
317 break;
318 default:
319 NS_FATAL_ERROR ("Unknown action in case of failure");
320 }
321 }
322}
323
324Time
326{
327 const WifiTxVector& txVector = ppdu->GetTxVector ();
328 return ppdu->GetTxDuration () - (GetDurationUpToField (field, txVector) + GetDuration (field, txVector));
329}
330
331bool
333{
334 NS_LOG_FUNCTION (this << field << *event);
335 NS_ASSERT (field != WIFI_PPDU_FIELD_PREAMBLE && field != WIFI_PPDU_FIELD_DATA); //handled apart for the time being
336 auto ppduFormats = GetPpduFormats ();
337 auto itFormat = ppduFormats.find (event->GetPpdu ()->GetPreamble ());
338 if (itFormat != ppduFormats.end ())
339 {
340 auto itField = std::find (itFormat->second.begin (), itFormat->second.end (), field);
341 if (itField != itFormat->second.end ())
342 {
343 return true; //supported field so we can start receiving
344 }
345 }
346 return false; //unsupported otherwise
347}
348
351{
352 NS_LOG_FUNCTION (this << field << *event);
353 NS_ASSERT (field != WIFI_PPDU_FIELD_DATA); //handled apart for the time being
354 if (field == WIFI_PPDU_FIELD_PREAMBLE)
355 {
356 return DoEndReceivePreamble (event);
357 }
358 return PhyFieldRxStatus (false); //failed reception by default
359}
360
361void
363 Time /* rxDuration */)
364{
365 //The total RX power corresponds to the maximum over all the bands
366 auto it = std::max_element (rxPowersW.begin (), rxPowersW.end (),
367 [] (const std::pair<WifiSpectrumBand, double> &p1, const std::pair<WifiSpectrumBand, double> &p2) {
368 return p1.second < p2.second;
369 });
370 NS_LOG_FUNCTION (this << ppdu << it->second);
371 Time rxDuration = ppdu->GetTxDuration (); //the actual duration of the PPDU should be considered
372
373 Ptr<Event> event = DoGetEvent (ppdu, rxPowersW);
374 if (event == nullptr)
375 {
376 //PPDU should be simply considered as interference (once it has been accounted for in InterferenceHelper)
377 return;
378 }
379
380 Time endRx = Simulator::Now () + rxDuration;
381 if (m_state->GetState () == WifiPhyState::OFF)
382 {
383 NS_LOG_DEBUG ("Cannot start RX because device is OFF");
384 if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
385 {
387 }
389 return;
390 }
391
392 if (ppdu->IsTruncatedTx ())
393 {
394 NS_LOG_DEBUG ("Packet reception stopped because transmitter has been switched off");
395 if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
396 {
398 }
400 return;
401 }
402
403 switch (m_state->GetState ())
404 {
406 NS_LOG_DEBUG ("Drop packet because of channel switching");
407 /*
408 * Packets received on the upcoming channel are added to the event list
409 * during the switching state. This way the medium can be correctly sensed
410 * when the device listens to the channel for the first time after the
411 * switching e.g. after channel switching, the channel may be sensed as
412 * busy due to other devices' transmissions started before the end of
413 * the switching.
414 */
416 break;
417 case WifiPhyState::RX:
420 && m_wifiPhy->m_frameCaptureModel->CaptureNewFrame (m_wifiPhy->m_currentEvent, event))
421 {
423 NS_LOG_DEBUG ("Switch to new packet");
425 }
426 else
427 {
428 NS_LOG_DEBUG ("Drop packet because already in Rx");
430 if (m_wifiPhy->m_currentEvent == 0)
431 {
432 /*
433 * We are here because the non-legacy PHY header has not been successfully received.
434 * The PHY is kept in RX state for the duration of the PPDU, but EndReceive function is
435 * not called when the reception of the PPDU is finished, which is responsible to clear
436 * m_currentPreambleEvents. As a result, m_currentPreambleEvents should be cleared here.
437 */
439 }
440 }
441 break;
442 case WifiPhyState::TX:
443 NS_LOG_DEBUG ("Drop packet because already in Tx");
445 break;
447 if (m_wifiPhy->m_currentEvent != 0)
448 {
451 && m_wifiPhy->m_frameCaptureModel->CaptureNewFrame (m_wifiPhy->m_currentEvent, event))
452 {
454 NS_LOG_DEBUG ("Switch to new packet");
456 }
457 else
458 {
459 NS_LOG_DEBUG ("Drop packet because already decoding preamble");
461 }
462 }
463 else
464 {
466 }
467 break;
471 break;
473 NS_LOG_DEBUG ("Drop packet because in sleep mode");
475 break;
476 default:
477 NS_FATAL_ERROR ("Invalid WifiPhy state.");
478 break;
479 }
480}
481
482void
483PhyEntity::DropPreambleEvent (Ptr<const WifiPpdu> ppdu, WifiPhyRxfailureReason reason, Time endRx, uint16_t measurementChannelWidth)
484{
485 NS_LOG_FUNCTION (this << ppdu << reason << endRx << measurementChannelWidth);
487 auto it = m_wifiPhy->m_currentPreambleEvents.find (std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()));
488 if (it != m_wifiPhy->m_currentPreambleEvents.end ())
489 {
491 }
492 if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
493 {
494 //that PPDU will be noise _after_ the end of the current event.
495 m_wifiPhy->SwitchMaybeToCcaBusy (measurementChannelWidth);
496 }
497}
498
499void
501{
502 NS_LOG_FUNCTION (this << ppdu << rxDuration);
503 auto it = m_wifiPhy->m_currentPreambleEvents.find (std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()));
504 if (it != m_wifiPhy->m_currentPreambleEvents.end ())
505 {
507 }
509 {
510 m_wifiPhy->Reset ();
511 }
512
513 if (rxDuration > m_state->GetDelayUntilIdle ())
514 {
515 //this PPDU will be noise _after_ the completion of the current event
517 }
518}
519
520uint16_t
522{
523 return SU_STA_ID;
524}
525
526void
528{
529 NS_LOG_FUNCTION (this << *event);
531 const WifiTxVector& txVector = event->GetTxVector ();
532 Time payloadDuration = event->GetPpdu ()->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
533
534 //TODO: Add method in WifiPhy to clear all other PHYs (since this one is starting Rx)
535 m_state->SwitchToRx (payloadDuration);
536 m_wifiPhy->m_phyRxPayloadBeginTrace (txVector, payloadDuration); //this callback (equivalent to PHY-RXSTART primitive) is triggered only if headers have been correctly decoded and that the mode within is supported
537
538 DoStartReceivePayload (event);
539}
540
541void
543{
544 NS_LOG_FUNCTION (this << *event);
545 Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
546 NS_LOG_DEBUG ("Receiving PSDU");
547 uint16_t staId = GetStaId (ppdu);
548 m_signalNoiseMap.insert ({std::make_pair (ppdu->GetUid (), staId), SignalNoiseDbm ()});
549 m_statusPerMpduMap.insert ({std::make_pair (ppdu->GetUid (), staId), std::vector<bool> ()});
550 ScheduleEndOfMpdus (event);
551 m_endRxPayloadEvents.push_back (Simulator::Schedule (ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (event->GetTxVector ()),
552 &PhyEntity::EndReceivePayload, this, event));
553}
554
555void
557{
558 NS_LOG_FUNCTION (this << *event);
559 Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
561 const WifiTxVector& txVector = event->GetTxVector ();
562 uint16_t staId = GetStaId (ppdu);
563 Time endOfMpduDuration = NanoSeconds (0);
564 Time relativeStart = NanoSeconds (0);
565 Time psduDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
566 Time remainingAmpduDuration = psduDuration;
567 size_t nMpdus = psdu->GetNMpdus ();
568 MpduType mpduType = (nMpdus > 1) ? FIRST_MPDU_IN_AGGREGATE : (psdu->IsSingle () ? SINGLE_MPDU : NORMAL_MPDU);
569 uint32_t totalAmpduSize = 0;
570 double totalAmpduNumSymbols = 0.0;
571 auto mpdu = psdu->begin ();
572 for (size_t i = 0; i < nMpdus && mpdu != psdu->end (); ++mpdu)
573 {
574 uint32_t size = (mpduType == NORMAL_MPDU) ? psdu->GetSize () : psdu->GetAmpduSubframeSize (i);
575 Time mpduDuration = m_wifiPhy->GetPayloadDuration (size, txVector,
576 m_wifiPhy->GetPhyBand (), mpduType, true, totalAmpduSize,
577 totalAmpduNumSymbols, staId);
578
579 remainingAmpduDuration -= mpduDuration;
580 if (i == (nMpdus - 1) && !remainingAmpduDuration.IsZero ()) //no more MPDUs coming
581 {
582 if (remainingAmpduDuration < NanoSeconds (txVector.GetGuardInterval ())) //enables to ignore padding
583 {
584 mpduDuration += remainingAmpduDuration; //apply a correction just in case rounding had induced slight shift
585 }
586 }
587
588 endOfMpduDuration += mpduDuration;
589 NS_LOG_INFO ("Schedule end of MPDU #" << i << " in " << endOfMpduDuration.As (Time::NS) <<
590 " (relativeStart=" << relativeStart.As (Time::NS) << ", mpduDuration=" << mpduDuration.As (Time::NS) <<
591 ", remainingAmdpuDuration=" << remainingAmpduDuration.As (Time::NS) << ")");
592 m_endOfMpduEvents.push_back (Simulator::Schedule (endOfMpduDuration, &PhyEntity::EndOfMpdu, this, event, Create<WifiPsdu> (*mpdu, false), i, relativeStart, mpduDuration));
593
594 //Prepare next iteration
595 ++i;
596 relativeStart += mpduDuration;
597 mpduType = (i == (nMpdus - 1)) ? LAST_MPDU_IN_AGGREGATE : MIDDLE_MPDU_IN_AGGREGATE;
598 }
599}
600
601void
602PhyEntity::EndOfMpdu (Ptr<Event> event, Ptr<const WifiPsdu> psdu, size_t mpduIndex, Time relativeStart, Time mpduDuration)
603{
604 NS_LOG_FUNCTION (this << *event << mpduIndex << relativeStart << mpduDuration);
605 Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
606 WifiTxVector txVector = event->GetTxVector ();
607 uint16_t staId = GetStaId (ppdu);
608
609 std::pair<bool, SignalNoiseDbm> rxInfo = GetReceptionStatus (psdu, event, staId, relativeStart, mpduDuration);
610 NS_LOG_DEBUG ("Extracted MPDU #" << mpduIndex << ": duration: " << mpduDuration.As (Time::NS) <<
611 ", correct reception: " << rxInfo.first << ", Signal/Noise: " << rxInfo.second.signal << "/" << rxInfo.second.noise << "dBm");
612
613 auto signalNoiseIt = m_signalNoiseMap.find (std::make_pair (ppdu->GetUid (), staId));
614 NS_ASSERT (signalNoiseIt != m_signalNoiseMap.end ());
615 signalNoiseIt->second = rxInfo.second;
616
617 RxSignalInfo rxSignalInfo;
618 rxSignalInfo.snr = rxInfo.second.signal / rxInfo.second.noise;
619 rxSignalInfo.rssi = rxInfo.second.signal;
620
621 auto statusPerMpduIt = m_statusPerMpduMap.find (std::make_pair (ppdu->GetUid (), staId));
622 NS_ASSERT (statusPerMpduIt != m_statusPerMpduMap.end ());
623 statusPerMpduIt->second.push_back (rxInfo.first);
624
625 if (rxInfo.first && GetAddressedPsduInPpdu (ppdu)->GetNMpdus () > 1)
626 {
627 //only done for correct MPDU that is part of an A-MPDU
628 m_state->ContinueRxNextMpdu (Copy (psdu), rxSignalInfo, txVector);
629 }
630}
631
632void
634{
635 Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
636 WifiTxVector txVector = event->GetTxVector ();
637 Time psduDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
638 NS_LOG_FUNCTION (this << *event << psduDuration);
639 NS_ASSERT (event->GetEndTime () == Simulator::Now ());
640 uint16_t staId = GetStaId (ppdu);
641 const auto & channelWidthAndBand = GetChannelWidthAndBand (event->GetTxVector (), staId);
642 double snr = m_wifiPhy->m_interference.CalculateSnr (event, channelWidthAndBand.first, txVector.GetNss (staId), channelWidthAndBand.second);
643
645 m_wifiPhy->NotifyRxEnd (psdu);
646
647 auto signalNoiseIt = m_signalNoiseMap.find (std::make_pair (ppdu->GetUid (), staId));
648 NS_ASSERT (signalNoiseIt != m_signalNoiseMap.end ());
649 auto statusPerMpduIt = m_statusPerMpduMap.find (std::make_pair (ppdu->GetUid (), staId));
650 NS_ASSERT (statusPerMpduIt != m_statusPerMpduMap.end ());
651
652 if (std::count (statusPerMpduIt->second.begin (), statusPerMpduIt->second.end (), true))
653 {
654 //At least one MPDU has been successfully received
655 m_wifiPhy->NotifyMonitorSniffRx (psdu, m_wifiPhy->GetFrequency (), txVector, signalNoiseIt->second, statusPerMpduIt->second, staId);
656 RxSignalInfo rxSignalInfo;
657 rxSignalInfo.snr = snr;
658 rxSignalInfo.rssi = signalNoiseIt->second.signal; //same information for all MPDUs
659 m_state->SwitchFromRxEndOk (Copy (psdu), rxSignalInfo, txVector, staId, statusPerMpduIt->second);
660 m_wifiPhy->m_previouslyRxPpduUid = ppdu->GetUid (); //store UID only if reception is successful (because otherwise trigger won't be read by MAC layer)
661 }
662 else
663 {
664 m_state->SwitchFromRxEndError (Copy (psdu), snr);
665 }
666
667 DoEndReceivePayload (ppdu);
669}
670
671void
673{
674 NS_LOG_FUNCTION (this << ppdu);
676 NotifyInterferenceRxEndAndClear (false); //don't reset WifiPhy
677
680 m_endRxPayloadEvents.clear ();
681}
682
683std::pair<bool, SignalNoiseDbm>
685 Time relativeMpduStart, Time mpduDuration)
686{
687 NS_LOG_FUNCTION (this << *psdu << *event << staId << relativeMpduStart << mpduDuration);
688 const auto & channelWidthAndBand = GetChannelWidthAndBand (event->GetTxVector (), staId);
689 SnrPer snrPer = m_wifiPhy->m_interference.CalculatePayloadSnrPer (event, channelWidthAndBand.first, channelWidthAndBand.second, staId,
690 std::make_pair (relativeMpduStart, relativeMpduStart + mpduDuration));
691
692 WifiMode mode = event->GetTxVector ().GetMode (staId);
693 NS_LOG_DEBUG ("rate=" << (mode.GetDataRate (event->GetTxVector (), staId)) <<
694 ", SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per << ", size=" << psdu->GetSize () <<
695 ", relativeStart = " << relativeMpduStart.As (Time::NS) << ", duration = " << mpduDuration.As (Time::NS));
696
697 // There are two error checks: PER and receive error model check.
698 // PER check models is typical for Wi-Fi and is based on signal modulation;
699 // Receive error model is optional, if we have an error model and
700 // it indicates that the packet is corrupt, drop the packet.
701 SignalNoiseDbm signalNoise;
702 signalNoise.signal = WToDbm (event->GetRxPowerW (channelWidthAndBand.second));
703 signalNoise.noise = WToDbm (event->GetRxPowerW (channelWidthAndBand.second) / snrPer.snr);
704 if (GetRandomValue () > snrPer.per
706 {
707 NS_LOG_DEBUG ("Reception succeeded: " << psdu);
708 return std::make_pair (true, signalNoise);
709 }
710 else
711 {
712 NS_LOG_DEBUG ("Reception failed: " << psdu);
713 return std::make_pair (false, signalNoise);
714 }
715}
716
717std::pair<uint16_t, WifiSpectrumBand>
718PhyEntity::GetChannelWidthAndBand (const WifiTxVector& txVector, uint16_t /* staId */) const
719{
720 uint16_t channelWidth = GetRxChannelWidth (txVector);
721 return std::make_pair (channelWidth, m_wifiPhy->GetPrimaryBand (channelWidth));
722}
723
724const std::map <std::pair<uint64_t, WifiPreamble>, Ptr<Event> > &
726{
728}
729
730void
732{
733 NS_LOG_FUNCTION (this << *event);
734 Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
735 m_wifiPhy->m_currentPreambleEvents.insert ({std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()), event});
736}
737
740{
741 Ptr<Event> event = CreateInterferenceEvent (ppdu, ppdu->GetTxVector (), ppdu->GetTxDuration (), rxPowersW);
742
743 //We store all incoming preamble events, and a decision is made at the end of the preamble detection window.
744 auto uidPreamblePair = std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ());
746 m_wifiPhy->m_currentPreambleEvents.insert ({uidPreamblePair, event});
747 return event;
748}
749
751PhyEntity::CreateInterferenceEvent (Ptr<const WifiPpdu> ppdu, const WifiTxVector& txVector, Time duration, RxPowerWattPerChannelBand& rxPower, bool isStartOfdmaRxing /* = false */)
752{
753 return m_wifiPhy->m_interference.Add (ppdu, txVector, duration, rxPower, isStartOfdmaRxing);
754}
755
756void
758{
759 m_wifiPhy->m_interference.UpdateEvent (event, rxPower);
760}
761
762void
764{
766 m_signalNoiseMap.clear ();
767 m_statusPerMpduMap.clear ();
768 for (const auto & endOfMpduEvent : m_endOfMpduEvents)
769 {
770 NS_ASSERT (endOfMpduEvent.IsExpired ());
771 }
772 m_endOfMpduEvents.clear ();
773 if (reset)
774 {
775 m_wifiPhy->Reset ();
776 }
777}
778
781{
782 NS_LOG_FUNCTION (this << *event);
783 NS_ASSERT (m_wifiPhy->m_currentPreambleEvents.size () == 1); //Synched on one after detection period
784 return PhyFieldRxStatus (true); //always consider that preamble has been correctly received if preamble detection was OK
785}
786
787void
789{
790 NS_LOG_FUNCTION (this << *event);
791 NS_LOG_DEBUG ("Sync to signal (power=" << WToDbm (GetRxPowerWForPpdu (event)) << "dBm)");
792 m_wifiPhy->m_interference.NotifyRxStart (); //We need to notify it now so that it starts recording events
794}
795
796void
798{
799 NS_LOG_FUNCTION (this << *event);
801 NS_ASSERT (m_wifiPhy->m_endPhyRxEvent.IsExpired ()); //since end of preamble reception is scheduled by this method upon success
802
803 //calculate PER on the measurement channel for PHY headers
804 uint16_t measurementChannelWidth = GetMeasurementChannelWidth (event->GetPpdu ());
805 auto measurementBand = m_wifiPhy->GetPrimaryBand (measurementChannelWidth);
806 double maxRxPowerW = -1; //in case current event may not be sent on measurement channel (rxPowerW would be equal to 0)
807 Ptr<Event> maxEvent;
809 for (auto preambleEvent : m_wifiPhy->m_currentPreambleEvents)
810 {
811 double rxPowerW = preambleEvent.second->GetRxPowerW (measurementBand);
812 if (rxPowerW > maxRxPowerW)
813 {
814 maxRxPowerW = rxPowerW;
815 maxEvent = preambleEvent.second;
816 }
817 }
818
819 NS_ASSERT (maxEvent != 0);
820 if (maxEvent != event)
821 {
822 NS_LOG_DEBUG ("Receiver got a stronger packet with UID " << maxEvent->GetPpdu ()->GetUid () << " during preamble detection: drop packet with UID " << event->GetPpdu ()->GetUid ());
824 auto it = m_wifiPhy->m_currentPreambleEvents.find (std::make_pair (event->GetPpdu ()->GetUid (), event->GetPpdu ()->GetPreamble ()));
826 //This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to the power at the start of the PPDU
827 m_wifiPhy->m_interference.NotifyRxEnd (maxEvent->GetStartTime ());
828 //Make sure InterferenceHelper keeps recording events
830 return;
831 }
832
833 m_wifiPhy->m_currentEvent = event;
834
835 double snr = m_wifiPhy->m_interference.CalculateSnr (m_wifiPhy->m_currentEvent, measurementChannelWidth, 1, measurementBand);
836 NS_LOG_DEBUG ("SNR(dB)=" << RatioToDb (snr) << " at end of preamble detection period");
837
838 if ((!m_wifiPhy->m_preambleDetectionModel && maxRxPowerW > 0.0)
839 || (m_wifiPhy->m_preambleDetectionModel && m_wifiPhy->m_preambleDetectionModel->IsPreambleDetected (m_wifiPhy->m_currentEvent->GetRxPowerW (measurementBand), snr, measurementChannelWidth)))
840 {
841 //A bit convoluted but it enables to sync all PHYs
842 for (auto & it : m_wifiPhy->m_phyEntities)
843 {
844 it.second->CancelRunningEndPreambleDetectionEvents (true);
845 }
846
847 for (auto it = m_wifiPhy->m_currentPreambleEvents.begin (); it != m_wifiPhy->m_currentPreambleEvents.end (); )
848 {
849 if (it->second != m_wifiPhy->m_currentEvent)
850 {
851 NS_LOG_DEBUG ("Drop packet with UID " << it->first.first << " and preamble " << it->first.second << " arrived at time " << it->second->GetStartTime ());
853 if (m_wifiPhy->m_currentEvent->GetPpdu ()->GetUid () > it->first.first)
854 {
856 //This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to the power at the start of the PPDU
858 }
859 else
860 {
861 reason = BUSY_DECODING_PREAMBLE;
862 }
863 m_wifiPhy->NotifyRxDrop (GetAddressedPsduInPpdu (it->second->GetPpdu ()), reason);
864 it = m_wifiPhy->m_currentPreambleEvents.erase (it);
865 }
866 else
867 {
868 ++it;
869 }
870 }
871
872 //Make sure InterferenceHelper keeps recording events
874
877
878 //Continue receiving preamble
879 Time durationTillEnd = GetDuration (WIFI_PPDU_FIELD_PREAMBLE, event->GetTxVector ()) - m_wifiPhy->GetPreambleDetectionDuration ();
880 m_state->SwitchMaybeToCcaBusy (durationTillEnd); //will be prolonged by next field
882 }
883 else
884 {
885 NS_LOG_DEBUG ("Drop packet because PHY preamble detection failed");
886 // Like CCA-SD, CCA-ED is governed by the 4 us CCA window to flag CCA-BUSY
887 // for any received signal greater than the CCA-ED threshold.
890 {
891 //Do not erase events if there are still pending preamble events to be processed
893 }
895 //Cancel preamble reception
897 }
898}
899
900bool
902{
903 WifiMode txMode = ppdu->GetTxVector ().GetMode ();
904 if (!IsModeSupported (txMode))
905 {
906 NS_LOG_DEBUG ("Drop packet because it was sent using an unsupported mode (" << txMode << ")");
907 return false;
908 }
909 return true;
910}
911
912void
914{
915 NS_LOG_FUNCTION (this);
916 for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
917 {
918 endPreambleDetectionEvent.Cancel ();
919 }
921 for (auto & endRxPayloadEvent : m_endRxPayloadEvents)
922 {
923 endRxPayloadEvent.Cancel ();
924 }
925 m_endRxPayloadEvents.clear ();
926 for (auto & endMpduEvent : m_endOfMpduEvents)
927 {
928 endMpduEvent.Cancel ();
929 }
930 m_endOfMpduEvents.clear ();
931}
932
933bool
935{
936 return m_endPreambleDetectionEvents.empty ();
937}
938
939void
941{
942 NS_LOG_FUNCTION (this << clear);
943 for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
944 {
945 if (endPreambleDetectionEvent.IsRunning ())
946 {
947 endPreambleDetectionEvent.Cancel ();
948 }
949 }
950 if (clear)
951 {
953 }
954}
955
956void
958{
959 NS_LOG_FUNCTION (this << reason);
962}
963
964void
966{
967 NS_LOG_FUNCTION (this << reason);
968 if (m_wifiPhy->m_currentEvent) //Otherwise abort has already been called just before
969 {
970 for (auto & endMpduEvent : m_endOfMpduEvents)
971 {
972 endMpduEvent.Cancel ();
973 }
974 m_endOfMpduEvents.clear ();
975 }
976}
977
978void
980{
981 NS_LOG_FUNCTION (this << *event);
982 DoResetReceive (event);
983 NS_ASSERT (m_endRxPayloadEvents.size () == 1 && m_endRxPayloadEvents.front ().IsExpired ());
984 m_endRxPayloadEvents.clear ();
985 m_wifiPhy->ResetReceive (event);
986}
987
988void
990{
991 NS_LOG_FUNCTION (this << *event);
992 NS_ASSERT (event->GetEndTime () == Simulator::Now ());
993}
994
995double
997{
998 return m_wifiPhy->m_random->GetValue ();
999}
1000
1001double
1003{
1004 return event->GetRxPowerW (m_wifiPhy->GetPrimaryBand (GetMeasurementChannelWidth (event->GetPpdu ())));
1005}
1006
1009{
1010 return m_wifiPhy->m_currentEvent;
1011}
1012
1013uint16_t
1015{
1016 return GetRxChannelWidth (ppdu->GetTxVector ());
1017}
1018
1019uint16_t
1021{
1022 return std::min (m_wifiPhy->GetChannelWidth (), txVector.GetChannelWidth ());
1023}
1024
1025uint64_t
1027{
1028 NS_LOG_FUNCTION (this);
1029 return m_globalPpduUid++;
1030}
1031
1032uint16_t
1034{
1035 NS_LOG_FUNCTION (this << txVector);
1036
1038}
1039
1040void
1041PhyEntity::NotifyPayloadBegin (const WifiTxVector& txVector, const Time& payloadDuration)
1042{
1043 m_wifiPhy->m_phyRxPayloadBeginTrace (txVector, payloadDuration);
1044}
1045
1046void
1048{
1049 NS_LOG_FUNCTION (this << ppdu);
1050 Transmit (ppdu->GetTxDuration (), ppdu, "transmission");
1051}
1052
1053void
1054PhyEntity::Transmit (Time txDuration, Ptr<WifiPpdu> ppdu, std::string type)
1055{
1056 NS_LOG_FUNCTION (this << txDuration << ppdu << type);
1057 double txPowerWatts = DbmToW (m_wifiPhy->GetTxPowerForTransmission (ppdu) + m_wifiPhy->GetTxGain ());
1058 NS_LOG_DEBUG ("Start " << type << ": signal power before antenna gain=" << WToDbm (txPowerWatts) << "dBm");
1059 Ptr<SpectrumValue> txPowerSpectrum = GetTxPowerSpectralDensity (txPowerWatts, ppdu);
1060 Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters> ();
1061 txParams->duration = txDuration;
1062 txParams->psd = txPowerSpectrum;
1063 txParams->ppdu = ppdu;
1064 txParams->txCenterFreq = GetCenterFrequencyForChannelWidth (ppdu->GetTxVector ());
1065 NS_LOG_DEBUG ("Starting " << type << " with power " << WToDbm (txPowerWatts) << " dBm on channel " << +m_wifiPhy->GetChannelNumber () << " for " << txParams->duration.As (Time::MS));
1066 NS_LOG_DEBUG ("Starting " << type << " with integrated spectrum power " << WToDbm (Integral (*txPowerSpectrum)) << " dBm; spectrum model Uid: " << txPowerSpectrum->GetSpectrumModel ()->GetUid ());
1067 auto spectrumWifiPhy = DynamicCast<SpectrumWifiPhy> (m_wifiPhy);
1068 NS_ASSERT (spectrumWifiPhy);
1069 spectrumWifiPhy->Transmit (txParams);
1070}
1071
1072uint16_t
1073PhyEntity::GetGuardBandwidth (uint16_t currentChannelWidth) const
1074{
1075 return m_wifiPhy->GetGuardBandwidth (currentChannelWidth);
1076}
1077
1078std::tuple<double, double, double>
1080{
1082}
1083
1084Time
1086{
1087 NS_ASSERT (psduMap.size () == 1);
1088 const auto & it = psduMap.begin ();
1089 return WifiPhy::CalculateTxDuration (it->second->GetSize (), txVector, band, it->first);
1090}
1091
1092} //namespace ns3
#define min(a, b)
Definition: 80211b.c:42
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
bool IsExpired(void) const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:65
void NotifyRxEnd(Time endTime)
Notify that RX has ended.
void NotifyRxStart()
Notify that RX has started.
double CalculateSnr(Ptr< Event > event, uint16_t channelWidth, uint8_t nss, WifiSpectrumBand band) const
Calculate the SNIR for the event (starting from now until the event end).
struct PhyEntity::SnrPer CalculatePhyHeaderSnrPer(Ptr< Event > event, uint16_t channelWidth, WifiSpectrumBand band, WifiPpduField header) const
Calculate the SNIR at the start of the PHY header and accumulate all SNIR changes in the SNIR vector.
struct PhyEntity::SnrPer CalculatePayloadSnrPer(Ptr< Event > event, uint16_t channelWidth, WifiSpectrumBand band, uint16_t staId, std::pair< Time, Time > relativeMpduStartStop) const
Calculate the SNIR at the start of the payload and accumulate all SNIR changes in the SNIR vector for...
Ptr< Event > Add(Ptr< const WifiPpdu > ppdu, const WifiTxVector &txVector, Time duration, RxPowerWattPerChannelBand &rxPower, bool isStartOfdmaRxing=false)
Add the PPDU-related signal to interference helper.
void UpdateEvent(Ptr< Event > event, const RxPowerWattPerChannelBand &rxPower)
Update event to scale its received power (W) per band.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
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:1041
const std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents(void) const
Get the map of current preamble events (stored in WifiPhy).
Definition: phy-entity.cc:725
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:780
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper of the WifiPhy (to make it reachable for child classes)
Definition: phy-entity.h:792
void EndPreambleDetectionPeriod(Ptr< Event > event)
End the preamble detection period.
Definition: phy-entity.cc:797
virtual Ptr< WifiPpdu > BuildPpdu(const WifiConstPsduMap &psdus, const WifiTxVector &txVector, Time ppduDuration)
Build amendment-specific PPDU.
Definition: phy-entity.cc:228
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:176
virtual uint64_t ObtainNextUid(const WifiTxVector &txVector)
Obtain the next UID for the PPDU to transmit.
Definition: phy-entity.cc:1026
virtual void CancelAllEvents(void)
Cancel and clear all running events.
Definition: phy-entity.cc:913
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:751
virtual void StartReceivePreamble(Ptr< WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW, Time rxDuration)
Start receiving the PHY preamble of a PPDU (i.e.
Definition: phy-entity.cc:362
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:807
Ptr< WifiPhy > m_wifiPhy
Pointer to the owning WifiPhy.
Definition: phy-entity.h:791
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:797
bool NoEndPreambleDetectionEvents(void) const
Definition: phy-entity.cc:934
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:718
std::list< WifiMode >::const_iterator end(void) const
Return a const iterator to past-the-last WifiMode.
Definition: phy-entity.cc:135
virtual ~PhyEntity()
Destructor for PHY entity.
Definition: phy-entity.cc:74
double GetRandomValue(void) const
Obtain a random value from the WifiPhy's generator.
Definition: phy-entity.cc:996
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:332
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition: phy-entity.cc:82
virtual bool HandlesMcsModes(void) const
Check if the WifiModes handled by this PHY are MCSs.
Definition: phy-entity.cc:123
std::list< WifiMode >::const_iterator begin(void) const
Return a const iterator to the first WifiMode.
Definition: phy-entity.cc:129
std::tuple< double, double, double > GetTxMaskRejectionParams(void) const
Definition: phy-entity.cc:1079
virtual const PpduFormats & GetPpduFormats(void) const =0
Return the PPDU formats of the PHY.
virtual void DoAbortCurrentReception(WifiPhyRxfailureReason reason)
Perform amendment-specific actions before aborting the current reception.
Definition: phy-entity.cc:965
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Abort the current reception.
Definition: phy-entity.cc:957
void EndReceivePayload(Ptr< Event > event)
The last symbol of the PPDU has arrived.
Definition: phy-entity.cc:633
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:809
PhyHeaderSections GetPhyHeaderSections(const WifiTxVector &txVector, Time ppduStart) const
Return a map of PHY header chunk information per PPDU field.
Definition: phy-entity.cc:209
virtual bool IsMcsSupported(uint8_t index) const
Check if the WifiMode corresponding to the given MCS index is supported.
Definition: phy-entity.cc:116
void StartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
Definition: phy-entity.cc:527
std::vector< EventId > m_endRxPayloadEvents
the end of receive events (only one unless UL MU reception)
Definition: phy-entity.h:799
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:989
void EndReceiveField(WifiPpduField field, Ptr< Event > event)
End receiving a given field.
Definition: phy-entity.cc:279
virtual Ptr< Event > DoGetEvent(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW)
Get the event corresponding to the incoming PPDU.
Definition: phy-entity.cc:739
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:141
WifiPpduField GetNextField(WifiPpduField currentField, WifiPreamble preamble) const
Return the field following the provided one.
Definition: phy-entity.cc:148
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Definition: phy-entity.h:301
double GetRxPowerWForPpdu(Ptr< Event > event) const
Obtain the received power (W) for a given band.
Definition: phy-entity.cc:1002
virtual void DoStartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
Definition: phy-entity.cc:542
Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector) const
Definition: phy-entity.cc:186
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:763
void StartPreambleDetectionPeriod(Ptr< Event > event)
Start the preamble detection period.
Definition: phy-entity.cc:788
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:236
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:806
virtual uint16_t GetRxChannelWidth(const WifiTxVector &txVector) const
Return the channel width used in the reception spectrum model.
Definition: phy-entity.cc:1020
void CancelRunningEndPreambleDetectionEvents(bool clear=false)
Cancel and eventually clear all end preamble detection events.
Definition: phy-entity.cc:940
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:325
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:521
virtual void StartTx(Ptr< WifiPpdu > ppdu)
This function is called by SpectrumWifiPhy to send the PPDU while performing amendment-specific actio...
Definition: phy-entity.cc:1047
virtual Time CalculateTxDuration(WifiConstPsduMap psduMap, const WifiTxVector &txVector, WifiPhyBand band) const
Definition: phy-entity.cc:1085
void StartReceiveField(WifiPpduField field, Ptr< Event > event)
Start receiving a given field.
Definition: phy-entity.cc:258
void Transmit(Time txDuration, Ptr< WifiPpdu > ppdu, std::string type)
This function prepares most of the WifiSpectrumSignalParameters parameters and invokes SpectrumWifiPh...
Definition: phy-entity.cc:1054
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const
Definition: phy-entity.cc:1073
virtual bool IsModeSupported(WifiMode mode) const
Check if the WifiMode is supported.
Definition: phy-entity.cc:90
void ResetReceive(Ptr< Event > event)
Reset PHY at the end of the PPDU under reception after it has failed the PHY header.
Definition: phy-entity.cc:979
std::list< WifiMode > m_modeList
the list of supported modes
Definition: phy-entity.h:794
std::vector< EventId > m_endPreambleDetectionEvents
the end of preamble detection events
Definition: phy-entity.h:796
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:203
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:250
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:500
void DropPreambleEvent(Ptr< const WifiPpdu > ppdu, WifiPhyRxfailureReason reason, Time endRx, uint16_t measurementChannelWidth)
Drop the PPDU and the corresponding preamble detection event, but keep CCA busy state after the compl...
Definition: phy-entity.cc:483
Ptr< const Event > GetCurrentEvent(void) const
Get the pointer to the current event (stored in WifiPhy).
Definition: phy-entity.cc:1008
virtual WifiMode GetMcs(uint8_t index) const
Get the WifiMode corresponding to the given MCS index.
Definition: phy-entity.cc:109
void AddPreambleEvent(Ptr< Event > event)
Add an entry to the map of current preamble events (stored in WifiPhy).
Definition: phy-entity.cc:731
virtual void DoEndReceivePayload(Ptr< const WifiPpdu > ppdu)
Perform amendment-specific actions at the end of the reception of the payload.
Definition: phy-entity.cc:672
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:1033
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:197
virtual bool IsConfigSupported(Ptr< const WifiPpdu > ppdu) const
Checks if the signaled configuration (excluding bandwidth) is supported by the PHY.
Definition: phy-entity.cc:901
virtual uint16_t GetMeasurementChannelWidth(const Ptr< const WifiPpdu > ppdu) const
Return the channel width used to measure the RSSI.
Definition: phy-entity.cc:1014
PhyRxFailureAction
Action to perform in case of RX failure.
Definition: phy-entity.h:101
@ DROP
drop PPDU and set CCA_BUSY
Definition: phy-entity.h:102
@ IGNORE
ignore the reception
Definition: phy-entity.h:104
@ ABORT
abort reception of PPDU
Definition: phy-entity.h:103
void UpdateInterferenceEvent(Ptr< Event > event, const RxPowerWattPerChannelBand &rxPower)
Update an event in WifiPhy's InterferenceHelper class.
Definition: phy-entity.cc:757
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:684
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:602
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:350
virtual uint8_t GetNumModes(void) const
Definition: phy-entity.cc:103
void ScheduleEndOfMpdus(Ptr< Event > event)
Schedule end of MPDUs events.
Definition: phy-entity.cc:556
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
SpectrumModelUid_t GetUid() const
Ptr< const SpectrumModel > GetSpectrumModel() const
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
@ MS
millisecond
Definition: nstime.h:115
@ NS
nanosecond
Definition: nstime.h:117
bool IsZero(void) const
Exactly equivalent to t == 0.
Definition: nstime.h:300
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:432
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
represent a single transmission mode
Definition: wifi-mode.h:48
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:114
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper.
Definition: wifi-phy.h:1136
Ptr< UniformRandomVariable > m_random
Provides uniform random variables.
Definition: wifi-phy.h:1135
uint8_t GetChannelNumber(void) const
Return current channel number.
Definition: wifi-phy.cc:895
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:1282
const WifiPhyOperatingChannel & GetOperatingChannel(void) const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:883
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:1145
bool IsStateRx(void) const
Definition: wifi-phy.cc:1804
WifiPhyBand GetPhyBand(void) const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:870
EventId m_endPhyRxEvent
the end of PHY receive event
Definition: wifi-phy.h:1141
void NotifyRxDrop(Ptr< const WifiPsdu > psdu, WifiPhyRxfailureReason reason)
Public method used to fire a PhyRxDrop trace.
Definition: wifi-phy.cc:1399
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Due to newly arrived signal, the current reception cannot be continued and has to be aborted.
Definition: wifi-phy.cc:1868
Ptr< FrameCaptureModel > m_frameCaptureModel
Frame capture model.
Definition: wifi-phy.h:1379
void NotifyRxBegin(Ptr< const WifiPsdu > psdu, const RxPowerWattPerChannelBand &rxPowersW)
Public method used to fire a PhyRxBegin trace.
Definition: wifi-phy.cc:1375
uint16_t GetMeasurementChannelWidth(const Ptr< const WifiPpdu > ppdu) const
Return the channel width used to measure the RSSI.
Definition: wifi-phy.cc:1963
void ResetReceive(Ptr< Event > event)
Reset PHY at the end of the packet under reception after it has failed the PHY header.
Definition: wifi-phy.cc:1644
virtual uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const =0
InterferenceHelper m_interference
the class handling interference computations
Definition: wifi-phy.h:1134
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1306
void Reset(void)
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1592
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1166
Ptr< ErrorModel > m_postReceptionErrorModel
Error model for receive packet events.
Definition: wifi-phy.h:1382
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1144
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1147
Ptr< PreambleDetectionModel > m_preambleDetectionModel
Preamble detection model.
Definition: wifi-phy.h:1380
void SwitchMaybeToCcaBusy(uint16_t channelWidth)
Check if PHY state should move to CCA busy state based on current state of interference tracker.
Definition: wifi-phy.cc:1852
virtual std::tuple< double, double, double > GetTxMaskRejectionParams(void) const =0
void NotifyRxEnd(Ptr< const WifiPsdu > psdu)
Public method used to fire a PhyRxEnd trace.
Definition: wifi-phy.cc:1387
WifiSpectrumBand GetPrimaryBand(uint16_t bandWidth)
If the operating channel width is a multiple of 20 MHz, return the start band index and the stop band...
Definition: wifi-phy.cc:1984
double GetTxGain(void) const
Return the transmission gain (dB).
Definition: wifi-phy.cc:494
double GetTxPowerForTransmission(Ptr< const WifiPpdu > ppdu) const
Compute the transmit power for the next transmission.
Definition: wifi-phy.cc:1923
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:1411
TracedCallback< WifiTxVector, Time > m_phyRxPayloadBeginTrace
The trace source fired when the reception of the PHY payload (PSDU) begins.
Definition: wifi-phy.h:1289
static Time GetPreambleDetectionDuration(void)
Definition: wifi-phy.cc:1270
Time m_timeLastPreambleDetected
Record the time the last preamble was detected.
Definition: wifi-phy.h:1383
Time GetLastRxEndTime(void) const
Return the end time of the last received packet.
Definition: wifi-phy.cc:1846
uint16_t GetChannelWidth(void) const
Definition: wifi-phy.cc:901
uint16_t GetFrequency(void) const
Definition: wifi-phy.cc:889
uint16_t GetPrimaryChannelCenterFrequency(uint16_t primaryChannelWidth) const
Get the center frequency of the primary channel of the given width.
uint32_t GetSize(void) const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:260
std::vector< Ptr< WifiMacQueueItem > >::const_iterator begin(void) const
Return a const iterator to the first MPDU.
Definition: wifi-psdu.cc:325
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:319
std::vector< Ptr< WifiMacQueueItem > >::const_iterator end(void) const
Return a const iterator to past-the-last MPDU.
Definition: wifi-psdu.cc:337
std::size_t GetAmpduSubframeSize(std::size_t i) const
Return the size of the i-th A-MPDU subframe.
Definition: wifi-psdu.cc:306
bool IsSingle(void) const
Return true if the PSDU is an S-MPDU.
Definition: wifi-psdu.cc:75
Ptr< const Packet > GetPacket(void) const
Get the PSDU as a single packet.
Definition: wifi-psdu.cc:87
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiPreamble GetPreambleType(void) 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(void) const
uint16_t GetGuardInterval(void) 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:67
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#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:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#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:281
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1268
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
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_PPDU_FIELD_SIG_B
SIG-B 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:49
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:43
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139
double Integral(const SpectrumValue &arg)
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:37
std::map< WifiSpectrumBand, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Definition: phy-entity.h:75
Ptr< T > Copy(Ptr< T > object)
Return a deep copy of a Ptr.
Definition: ptr.h:555
def start()
Definition: core.py:1853
Declaration of:
Status of the reception of the PPDU field.
Definition: phy-entity.h:111
WifiPhyRxfailureReason reason
failure reason
Definition: phy-entity.h:114
PhyRxFailureAction actionIfFailure
action to perform in case of failure
Definition: phy-entity.h:115
bool isSuccess
outcome (true if success) of the reception
Definition: phy-entity.h:113
A struct for both SNR and PER.
Definition: phy-entity.h:137
double snr
SNR in linear scale.
Definition: phy-entity.h:138
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:67
double rssi
RSSI in dBm.
Definition: phy-entity.h:69
double snr
SNR in linear scale.
Definition: phy-entity.h:68
SignalNoiseDbm structure.
Definition: phy-entity.h:53
double noise
noise power in dBm
Definition: phy-entity.h:55
double signal
signal strength in dBm
Definition: phy-entity.h:54
#define SU_STA_ID
Definition: wifi-mode.h:32
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ SWITCHING
The PHY layer is switching to other channel.
@ RX
The PHY layer is receiving a packet.
@ TX
The PHY layer is sending a packet.
@ OFF
The PHY layer is switched off.
@ SLEEP
The PHY layer is sleeping.
@ IDLE
The PHY layer is IDLE.