A Discrete-Event Network Simulator
API
wifi-phy-state-helper.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2005,2006 INRIA
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 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 */
20
21#include <algorithm>
22#include "ns3/log.h"
23#include "ns3/simulator.h"
24#include "ns3/packet.h"
26#include "wifi-tx-vector.h"
27#include "wifi-phy-listener.h"
28#include "wifi-psdu.h"
29#include "wifi-phy.h"
30
31namespace ns3 {
32
33NS_LOG_COMPONENT_DEFINE ("WifiPhyStateHelper");
34
35NS_OBJECT_ENSURE_REGISTERED (WifiPhyStateHelper);
36
37TypeId
39{
40 static TypeId tid = TypeId ("ns3::WifiPhyStateHelper")
41 .SetParent<Object> ()
42 .SetGroupName ("Wifi")
43 .AddConstructor<WifiPhyStateHelper> ()
44 .AddTraceSource ("State",
45 "The state of the PHY layer",
47 "ns3::WifiPhyStateHelper::StateTracedCallback")
48 .AddTraceSource ("RxOk",
49 "A packet has been received successfully.",
51 "ns3::WifiPhyStateHelper::RxOkTracedCallback")
52 .AddTraceSource ("RxError",
53 "A packet has been received unsuccessfully.",
55 "ns3::WifiPhyStateHelper::RxEndErrorTracedCallback")
56 .AddTraceSource ("Tx", "Packet transmission is starting.",
58 "ns3::WifiPhyStateHelper::TxTracedCallback")
59 ;
60 return tid;
61}
62
64 : m_sleeping (false),
65 m_isOff (false),
66 m_endTx (Seconds (0)),
67 m_endRx (Seconds (0)),
68 m_endCcaBusy (Seconds (0)),
69 m_endSwitching (Seconds (0)),
70 m_startTx (Seconds (0)),
71 m_startRx (Seconds (0)),
72 m_startCcaBusy (Seconds (0)),
73 m_startSwitching (Seconds (0)),
74 m_startSleep (Seconds (0)),
75 m_previousStateChangeTime (Seconds (0))
76{
77 NS_LOG_FUNCTION (this);
78}
79
80void
82{
83 m_rxOkCallback = callback;
84}
85
86void
88{
89 m_rxErrorCallback = callback;
90}
91
92void
94{
95 m_listeners.push_back (listener);
96}
97
98void
100{
101 ListenersI i = find (m_listeners.begin (), m_listeners.end (), listener);
102 if (i != m_listeners.end ())
103 {
104 m_listeners.erase (i);
105 }
106}
107
108bool
110{
111 return (GetState () == WifiPhyState::IDLE);
112}
113
114bool
116{
117 return (GetState () == WifiPhyState::CCA_BUSY);
118}
119
120bool
122{
123 return (GetState () == WifiPhyState::RX);
124}
125
126bool
128{
129 return (GetState () == WifiPhyState::TX);
130}
131
132bool
134{
135 return (GetState () == WifiPhyState::SWITCHING);
136}
137
138bool
140{
141 return (GetState () == WifiPhyState::SLEEP);
142}
143
144bool
146{
147 return (GetState () == WifiPhyState::OFF);
148}
149
150Time
152{
153 Time retval;
154
155 switch (GetState ())
156 {
157 case WifiPhyState::RX:
158 retval = m_endRx - Simulator::Now ();
159 break;
160 case WifiPhyState::TX:
161 retval = m_endTx - Simulator::Now ();
162 break;
164 retval = m_endCcaBusy - Simulator::Now ();
165 break;
167 retval = m_endSwitching - Simulator::Now ();
168 break;
172 retval = Seconds (0);
173 break;
174 default:
175 NS_FATAL_ERROR ("Invalid WifiPhy state.");
176 retval = Seconds (0);
177 break;
178 }
179 retval = Max (retval, Seconds (0));
180 return retval;
181}
182
183Time
185{
186 return m_startRx;
187}
188
189Time
191{
192 return m_endRx;
193}
194
197{
198 if (m_isOff)
199 {
200 return WifiPhyState::OFF;
201 }
202 if (m_sleeping)
203 {
204 return WifiPhyState::SLEEP;
205 }
206 else if (m_endTx > Simulator::Now ())
207 {
208 return WifiPhyState::TX;
209 }
210 else if (m_endRx > Simulator::Now ())
211 {
212 return WifiPhyState::RX;
213 }
214 else if (m_endSwitching > Simulator::Now ())
215 {
217 }
218 else if (m_endCcaBusy > Simulator::Now ())
219 {
221 }
222 else
223 {
224 return WifiPhyState::IDLE;
225 }
226}
227
228void
229WifiPhyStateHelper::NotifyTxStart (Time duration, double txPowerDbm)
230{
231 NS_LOG_FUNCTION (this);
232 for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
233 {
234 (*i)->NotifyTxStart (duration, txPowerDbm);
235 }
236}
237
238void
240{
241 NS_LOG_FUNCTION (this);
242 for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
243 {
244 (*i)->NotifyRxStart (duration);
245 }
246}
247
248void
250{
251 NS_LOG_FUNCTION (this);
252 for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
253 {
254 (*i)->NotifyRxEndOk ();
255 }
256}
257
258void
260{
261 NS_LOG_FUNCTION (this);
262 for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
263 {
264 (*i)->NotifyRxEndError ();
265 }
266}
267
268void
270{
271 NS_LOG_FUNCTION (this);
272 for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
273 {
274 (*i)->NotifyMaybeCcaBusyStart (duration);
275 }
276}
277
278void
280{
281 NS_LOG_FUNCTION (this);
282 for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
283 {
284 (*i)->NotifySwitchingStart (duration);
285 }
286}
287
288void
290{
291 NS_LOG_FUNCTION (this);
292 for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
293 {
294 (*i)->NotifySleep ();
295 }
296}
297
298void
300{
301 NS_LOG_FUNCTION (this);
302 for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
303 {
304 (*i)->NotifyOff ();
305 }
306}
307
308void
310{
311 NS_LOG_FUNCTION (this);
312 for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
313 {
314 (*i)->NotifyWakeup ();
315 }
316}
317
318void
320{
321 NS_LOG_FUNCTION (this);
322 for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
323 {
324 (*i)->NotifyOn ();
325 }
326}
327
328void
330{
331 NS_LOG_FUNCTION (this);
332 Time now = Simulator::Now ();
333 Time idleStart = Max (m_endCcaBusy, m_endRx);
334 idleStart = Max (idleStart, m_endTx);
335 idleStart = Max (idleStart, m_endSwitching);
336 NS_ASSERT (idleStart <= now);
340 {
341 Time ccaBusyStart = Max (m_endTx, m_endRx);
342 ccaBusyStart = Max (ccaBusyStart, m_startCcaBusy);
343 ccaBusyStart = Max (ccaBusyStart, m_endSwitching);
344 Time ccaBusyDuration = idleStart - ccaBusyStart;
345 if (ccaBusyDuration.IsStrictlyPositive ())
346 {
347 m_stateLogger (ccaBusyStart, ccaBusyDuration, WifiPhyState::CCA_BUSY);
348 }
349 }
350 Time idleDuration = now - idleStart;
351 if (idleDuration.IsStrictlyPositive ())
352 {
353 m_stateLogger (idleStart, idleDuration, WifiPhyState::IDLE);
354 }
355}
356
357void
358WifiPhyStateHelper::SwitchToTx (Time txDuration, WifiConstPsduMap psdus, double txPowerDbm, WifiTxVector txVector)
359{
360 NS_LOG_FUNCTION (this << txDuration << psdus << txPowerDbm << txVector);
361 if (!m_txTrace.IsEmpty ())
362 {
363 for (auto const& psdu : psdus)
364 {
365 m_txTrace (psdu.second->GetPacket (), txVector.GetMode (psdu.first),
366 txVector.GetPreambleType (), txVector.GetTxPowerLevel ());
367 }
368 }
369 Time now = Simulator::Now ();
370 switch (GetState ())
371 {
372 case WifiPhyState::RX:
373 /* The packet which is being received as well
374 * as its endRx event are cancelled by the caller.
375 */
377 m_endRx = now;
378 break;
380 {
381 Time ccaStart = Max (m_endRx, m_endTx);
382 ccaStart = Max (ccaStart, m_startCcaBusy);
383 ccaStart = Max (ccaStart, m_endSwitching);
384 m_stateLogger (ccaStart, now - ccaStart, WifiPhyState::CCA_BUSY);
385 } break;
388 break;
389 default:
390 NS_FATAL_ERROR ("Invalid WifiPhy state.");
391 break;
392 }
393 m_stateLogger (now, txDuration, WifiPhyState::TX);
395 m_endTx = now + txDuration;
396 m_startTx = now;
397 NotifyTxStart (txDuration, txPowerDbm);
398}
399
400void
402{
403 NS_LOG_FUNCTION (this << rxDuration);
405 Time now = Simulator::Now ();
406 switch (GetState ())
407 {
410 break;
412 {
413 Time ccaStart = Max (m_endRx, m_endTx);
414 ccaStart = Max (ccaStart, m_startCcaBusy);
415 ccaStart = Max (ccaStart, m_endSwitching);
416 m_stateLogger (ccaStart, now - ccaStart, WifiPhyState::CCA_BUSY);
417 } break;
418 default:
419 NS_FATAL_ERROR ("Invalid WifiPhy state " << GetState ());
420 break;
421 }
423 m_startRx = now;
424 m_endRx = now + rxDuration;
425 NotifyRxStart (rxDuration);
426 NS_ASSERT (IsStateRx ());
427}
428
429void
431{
432 NS_LOG_FUNCTION (this << switchingDuration);
433 Time now = Simulator::Now ();
434 switch (GetState ())
435 {
436 case WifiPhyState::RX:
437 /* The packet which is being received as well
438 * as its endRx event are cancelled by the caller.
439 */
441 m_endRx = now;
442 break;
444 {
445 Time ccaStart = Max (m_endRx, m_endTx);
446 ccaStart = Max (ccaStart, m_startCcaBusy);
447 ccaStart = Max (ccaStart, m_endSwitching);
448 m_stateLogger (ccaStart, now - ccaStart, WifiPhyState::CCA_BUSY);
449 } break;
452 break;
453 default:
454 NS_FATAL_ERROR ("Invalid WifiPhy state.");
455 break;
456 }
457
458 if (now < m_endCcaBusy)
459 {
460 m_endCcaBusy = now;
461 }
462
463 m_stateLogger (now, switchingDuration, WifiPhyState::SWITCHING);
465 m_startSwitching = now;
466 m_endSwitching = now + switchingDuration;
467 NotifySwitchingStart (switchingDuration);
469}
470
471void
473{
474 NS_LOG_FUNCTION (this << *psdu << rxSignalInfo << txVector);
475 std::vector<bool> statusPerMpdu;
476 if (!m_rxOkCallback.IsNull ())
477 {
478 m_rxOkCallback (psdu, rxSignalInfo, txVector, statusPerMpdu);
479 }
480}
481
482void
483WifiPhyStateHelper::SwitchFromRxEndOk (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, uint16_t staId, std::vector<bool> statusPerMpdu)
484{
485 NS_LOG_FUNCTION (this << *psdu << rxSignalInfo << txVector << staId << statusPerMpdu.size () <<
486 std::all_of(statusPerMpdu.begin(), statusPerMpdu.end(), [](bool v) { return v; })); //returns true if all true
487 NS_ASSERT (statusPerMpdu.size () != 0);
488 NS_ASSERT (Abs (m_endRx - Simulator::Now ()) < MicroSeconds (1)); //1us corresponds to the maximum propagation delay (delay spread)
489 //TODO: a better fix would be to call the function once all HE TB PPDUs are received
490 if (!m_rxOkTrace.IsEmpty ())
491 {
492 m_rxOkTrace (psdu->GetPacket (), rxSignalInfo.snr, txVector.GetMode (staId),
493 txVector.GetPreambleType ());
494 }
495 NotifyRxEndOk ();
497 if (!m_rxOkCallback.IsNull ())
498 {
499 m_rxOkCallback (psdu, rxSignalInfo, txVector, statusPerMpdu);
500 }
501}
502
503void
505{
506 NS_LOG_FUNCTION (this << *psdu << snr);
507 NS_ASSERT (Abs (m_endRx - Simulator::Now ()) < MicroSeconds (1)); //1us corresponds to the maximum propagation delay (delay spread)
508 //TODO: a better fix would be to call the function once all HE TB PPDUs are received
509 if (!m_rxErrorTrace.IsEmpty ())
510 {
511 m_rxErrorTrace (psdu->GetPacket (), snr);
512 }
516 {
517 m_rxErrorCallback (psdu);
518 }
519}
520
521void
523{
524 NS_LOG_FUNCTION (this);
525 Time now = Simulator::Now ();
530}
531
532void
534{
535 NS_LOG_FUNCTION (this << duration);
536 if (GetState () != WifiPhyState::RX)
537 {
538 NotifyMaybeCcaBusyStart (duration);
539 }
540 Time now = Simulator::Now ();
541 switch (GetState ())
542 {
545 break;
546 case WifiPhyState::RX:
547 return;
548 default:
549 break;
550 }
552 {
553 m_startCcaBusy = now;
554 }
555 m_endCcaBusy = std::max (m_endCcaBusy, now + duration);
556}
557
558void
560{
561 NS_LOG_FUNCTION (this);
562 Time now = Simulator::Now ();
563 switch (GetState ())
564 {
567 break;
569 {
570 Time ccaStart = Max (m_endRx, m_endTx);
571 ccaStart = Max (ccaStart, m_startCcaBusy);
572 ccaStart = Max (ccaStart, m_endSwitching);
573 m_stateLogger (ccaStart, now - ccaStart, WifiPhyState::CCA_BUSY);
574 } break;
575 default:
576 NS_FATAL_ERROR ("Invalid WifiPhy state.");
577 break;
578 }
580 m_sleeping = true;
581 m_startSleep = now;
582 NotifySleep ();
584}
585
586void
588{
589 NS_LOG_FUNCTION (this << duration);
591 Time now = Simulator::Now ();
594 m_sleeping = false;
595 NotifyWakeup ();
596 //update m_endCcaBusy after the sleep period
597 m_endCcaBusy = std::max (m_endCcaBusy, now + duration);
598 if (m_endCcaBusy > now)
599 {
601 }
602}
603
604void
606{
607 NS_LOG_FUNCTION (this);
608 NS_ASSERT (IsStateCcaBusy ()); //abort is called (with OBSS_PD_CCA_RESET reason) before RX is set by payload start
609 NotifyRxEndOk ();
614}
615
616void
618{
619 NS_LOG_FUNCTION (this);
620 Time now = Simulator::Now ();
621 switch (GetState ())
622 {
623 case WifiPhyState::RX:
624 /* The packet which is being received as well
625 * as its endRx event are cancelled by the caller.
626 */
628 m_endRx = now;
629 break;
630 case WifiPhyState::TX:
631 /* The packet which is being transmitted as well
632 * as its endTx event are cancelled by the caller.
633 */
635 m_endTx = now;
636 break;
639 break;
641 {
642 Time ccaStart = Max (m_endRx, m_endTx);
643 ccaStart = Max (ccaStart, m_startCcaBusy);
644 ccaStart = Max (ccaStart, m_endSwitching);
645 m_stateLogger (ccaStart, now - ccaStart, WifiPhyState::CCA_BUSY);
646 } break;
647 default:
648 NS_FATAL_ERROR ("Invalid WifiPhy state.");
649 break;
650 }
652 m_isOff = true;
653 NotifyOff ();
655}
656
657void
659{
660 NS_LOG_FUNCTION (this << duration);
662 Time now = Simulator::Now ();
664 m_isOff = false;
665 NotifyOn ();
666 //update m_endCcaBusy after the off period
667 m_endCcaBusy = std::max (m_endCcaBusy, now + duration);
668 if (m_endCcaBusy > now)
669 {
671 }
672}
673
674} //namespace ns3
#define max(a, b)
Definition: 80211b.c:43
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
A base class which provides memory management and object aggregation.
Definition: object.h:88
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
bool IsStrictlyPositive(void) const
Exactly equivalent to t > 0.
Definition: nstime.h:332
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
receive notifications about PHY events.
This objects implements the PHY state machine of the Wifi device.
bool IsStateSleep(void) const
Check whether the current state is SLEEP.
void SwitchToRx(Time rxDuration)
Switch state to RX for the given duration.
bool IsStateCcaBusy(void) const
Check whether the current state is CCA busy.
Time GetLastRxEndTime(void) const
Return the time the last RX end.
void SwitchFromRxEndOk(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, uint16_t staId, std::vector< bool > statusPerMpdu)
Switch from RX after the reception was successful.
Time GetDelayUntilIdle(void) const
Return the time before the state is back to IDLE.
void DoSwitchFromRx(void)
Switch the state from RX.
Time GetLastRxStartTime(void) const
Return the time the last RX start.
void SwitchFromOff(Time duration)
Switch from off mode.
WifiPhyState GetState(void) const
Return the current state of WifiPhy.
bool IsStateOff(void) const
Check whether the current state is OFF.
bool IsStateTx(void) const
Check whether the current state is TX.
void NotifyOn(void)
Notify all WifiPhyListener that we are going to switch on.
bool IsStateRx(void) const
Check whether the current state is RX.
void NotifySwitchingStart(Time duration)
Notify all WifiPhyListener that we are switching channel with the given channel switching delay.
Time m_previousStateChangeTime
previous state change time
void NotifyRxStart(Time duration)
Notify all WifiPhyListener that the reception has started for the given duration.
void SwitchToChannelSwitching(Time switchingDuration)
Switch state to channel switching for the given duration.
void NotifyRxEndOk(void)
Notify all WifiPhyListener that the reception was successful.
TracedCallback< Ptr< const Packet >, WifiMode, WifiPreamble, uint8_t > m_txTrace
transmit trace callback
Time m_endSwitching
end switching
Time m_startSwitching
start switching
TracedCallback< Time, Time, WifiPhyState > m_stateLogger
The trace source fired when state is changed.
void LogPreviousIdleAndCcaBusyStates(void)
Log the ideal and CCA states.
void RegisterListener(WifiPhyListener *listener)
Register WifiPhyListener to this WifiPhyStateHelper.
void ContinueRxNextMpdu(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector)
Continue RX after the reception of an MPDU in an A-MPDU was successful.
void SwitchToTx(Time txDuration, WifiConstPsduMap psdus, double txPowerDbm, WifiTxVector txVector)
Switch state to TX for the given duration.
RxOkCallback m_rxOkCallback
receive OK callback
void SwitchFromRxAbort(void)
Abort current reception.
TracedCallback< Ptr< const Packet >, double, WifiMode, WifiPreamble > m_rxOkTrace
receive OK trace callback
bool IsStateSwitching(void) const
Check whether the current state is SWITCHING.
RxErrorCallback m_rxErrorCallback
receive error callback
void NotifyOff(void)
Notify all WifiPhyListener that we are going to switch off.
TracedCallback< Ptr< const Packet >, double > m_rxErrorTrace
receive error trace callback
Time m_startCcaBusy
start CCA busy
void NotifyTxStart(Time duration, double txPowerDbm)
Notify all WifiPhyListener that the transmission has started for the given duration.
Listeners m_listeners
listeners
static TypeId GetTypeId(void)
Get the type ID.
void SwitchToOff(void)
Switch to off mode.
void SwitchFromRxEndError(Ptr< WifiPsdu > psdu, double snr)
Switch from RX after the reception failed.
void SetReceiveOkCallback(RxOkCallback callback)
Set a callback for a successful reception.
void SwitchMaybeToCcaBusy(Time duration)
Switch to CCA busy.
std::vector< WifiPhyListener * >::iterator ListenersI
typedef for a list of WifiPhyListeners iterator
void SwitchToSleep(void)
Switch to sleep mode.
void SwitchFromSleep(Time duration)
Switch from sleep mode.
bool IsStateIdle(void) const
Check whether the current state is IDLE.
void NotifyRxEndError(void)
Notify all WifiPhyListener that the reception was not successful.
void SetReceiveErrorCallback(RxErrorCallback callback)
Set a callback for a failed reception.
void UnregisterListener(WifiPhyListener *listener)
Remove WifiPhyListener from this WifiPhyStateHelper.
void NotifySleep(void)
Notify all WifiPhyListener that we are going to sleep.
void NotifyWakeup(void)
Notify all WifiPhyListener that we woke up.
void NotifyMaybeCcaBusyStart(Time duration)
Notify all WifiPhyListener that the CCA has started for the given duration.
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...
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
uint8_t GetTxPowerLevel(void) const
WifiPreamble GetPreambleType(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
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:230
int64x64_t Abs(const int64x64_t &value)
Absolute value.
Definition: int64x64.h:205
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:67
double snr
SNR in linear scale.
Definition: phy-entity.h:68
WifiPhyState
The state of the PHY layer.
@ 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.