A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 #include "wifi-phy-state-helper.h"
21 #include "ns3/log.h"
22 #include "ns3/simulator.h"
23 #include "ns3/trace-source-accessor.h"
24 
25 NS_LOG_COMPONENT_DEFINE ("WifiPhyStateHelper");
26 
27 namespace ns3 {
28 
29 NS_OBJECT_ENSURE_REGISTERED (WifiPhyStateHelper);
30 
31 TypeId
33 {
34  static TypeId tid = TypeId ("ns3::WifiPhyStateHelper")
35  .SetParent<Object> ()
36  .AddConstructor<WifiPhyStateHelper> ()
37  .AddTraceSource ("State",
38  "The state of the PHY layer",
40  .AddTraceSource ("RxOk",
41  "A packet has been received successfully.",
43  .AddTraceSource ("RxError",
44  "A packet has been received unsuccessfully.",
46  .AddTraceSource ("Tx", "Packet transmission is starting.",
48  ;
49  return tid;
50 }
51 
53  : m_rxing (false),
54  m_endTx (Seconds (0)),
55  m_endRx (Seconds (0)),
56  m_endCcaBusy (Seconds (0)),
57  m_endSwitching (Seconds (0)),
58  m_startTx (Seconds (0)),
59  m_startRx (Seconds (0)),
60  m_startCcaBusy (Seconds (0)),
61  m_startSwitching (Seconds (0)),
62  m_previousStateChangeTime (Seconds (0))
63 {
64  NS_LOG_FUNCTION (this);
65 }
66 
67 void
69 {
70  m_rxOkCallback = callback;
71 }
72 void
74 {
75  m_rxErrorCallback = callback;
76 }
77 void
79 {
80  m_listeners.push_back (listener);
81 }
82 
83 bool
85 {
86  return (GetState () == WifiPhy::IDLE);
87 }
88 bool
90 {
91  return (GetState () != WifiPhy::IDLE);
92 }
93 bool
95 {
96  return (GetState () == WifiPhy::CCA_BUSY);
97 }
98 bool
100 {
101  return (GetState () == WifiPhy::RX);
102 }
103 bool
105 {
106  return (GetState () == WifiPhy::TX);
107 }
108 bool
110 {
111  return (GetState () == WifiPhy::SWITCHING);
112 }
113 
114 
115 
116 Time
118 {
120 }
121 
122 Time
124 {
125  Time retval;
126 
127  switch (GetState ())
128  {
129  case WifiPhy::RX:
130  retval = m_endRx - Simulator::Now ();
131  break;
132  case WifiPhy::TX:
133  retval = m_endTx - Simulator::Now ();
134  break;
135  case WifiPhy::CCA_BUSY:
136  retval = m_endCcaBusy - Simulator::Now ();
137  break;
138  case WifiPhy::SWITCHING:
139  retval = m_endSwitching - Simulator::Now ();
140  break;
141  case WifiPhy::IDLE:
142  retval = Seconds (0);
143  break;
144  default:
145  NS_FATAL_ERROR ("Invalid WifiPhy state.");
146  retval = Seconds (0);
147  break;
148  }
149  retval = Max (retval, Seconds (0));
150  return retval;
151 }
152 
153 Time
155 {
156  return m_startRx;
157 }
158 
159 enum WifiPhy::State
161 {
162  if (m_endTx > Simulator::Now ())
163  {
164  return WifiPhy::TX;
165  }
166  else if (m_rxing)
167  {
168  return WifiPhy::RX;
169  }
170  else if (m_endSwitching > Simulator::Now ())
171  {
172  return WifiPhy::SWITCHING;
173  }
174  else if (m_endCcaBusy > Simulator::Now ())
175  {
176  return WifiPhy::CCA_BUSY;
177  }
178  else
179  {
180  return WifiPhy::IDLE;
181  }
182 }
183 
184 
185 void
187 {
188  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
189  {
190  (*i)->NotifyTxStart (duration);
191  }
192 }
193 void
195 {
196  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
197  {
198  (*i)->NotifyRxStart (duration);
199  }
200 }
201 void
203 {
204  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
205  {
206  (*i)->NotifyRxEndOk ();
207  }
208 }
209 void
211 {
212  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
213  {
214  (*i)->NotifyRxEndError ();
215  }
216 }
217 void
219 {
220  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
221  {
222  (*i)->NotifyMaybeCcaBusyStart (duration);
223  }
224 }
225 void
227 {
228  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
229  {
230  (*i)->NotifySwitchingStart (duration);
231  }
232 }
233 
234 void
236 {
237  Time now = Simulator::Now ();
238  Time idleStart = Max (m_endCcaBusy, m_endRx);
239  idleStart = Max (idleStart, m_endTx);
240  idleStart = Max (idleStart, m_endSwitching);
241  NS_ASSERT (idleStart <= now);
242  if (m_endCcaBusy > m_endRx
244  && m_endCcaBusy > m_endTx)
245  {
246  Time ccaBusyStart = Max (m_endTx, m_endRx);
247  ccaBusyStart = Max (ccaBusyStart, m_startCcaBusy);
248  ccaBusyStart = Max (ccaBusyStart, m_endSwitching);
249  m_stateLogger (ccaBusyStart, idleStart - ccaBusyStart, WifiPhy::CCA_BUSY);
250  }
251  m_stateLogger (idleStart, now - idleStart, WifiPhy::IDLE);
252 }
253 
254 void
256  WifiPreamble preamble, uint8_t txPower)
257 {
258  m_txTrace (packet, txMode, preamble, txPower);
259  NotifyTxStart (txDuration);
260  Time now = Simulator::Now ();
261  switch (GetState ())
262  {
263  case WifiPhy::RX:
264  /* The packet which is being received as well
265  * as its endRx event are cancelled by the caller.
266  */
267  m_rxing = false;
269  m_endRx = now;
270  break;
271  case WifiPhy::CCA_BUSY:
272  {
273  Time ccaStart = Max (m_endRx, m_endTx);
274  ccaStart = Max (ccaStart, m_startCcaBusy);
275  ccaStart = Max (ccaStart, m_endSwitching);
276  m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
277  } break;
278  case WifiPhy::IDLE:
280  break;
281  case WifiPhy::SWITCHING:
282  default:
283  NS_FATAL_ERROR ("Invalid WifiPhy state.");
284  break;
285  }
286  m_stateLogger (now, txDuration, WifiPhy::TX);
288  m_endTx = now + txDuration;
289  m_startTx = now;
290 }
291 void
293 {
295  NS_ASSERT (!m_rxing);
296  NotifyRxStart (rxDuration);
297  Time now = Simulator::Now ();
298  switch (GetState ())
299  {
300  case WifiPhy::IDLE:
302  break;
303  case WifiPhy::CCA_BUSY:
304  {
305  Time ccaStart = Max (m_endRx, m_endTx);
306  ccaStart = Max (ccaStart, m_startCcaBusy);
307  ccaStart = Max (ccaStart, m_endSwitching);
308  m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
309  } break;
310  case WifiPhy::SWITCHING:
311  case WifiPhy::RX:
312  case WifiPhy::TX:
313  NS_FATAL_ERROR ("Invalid WifiPhy state.");
314  break;
315  }
317  m_rxing = true;
318  m_startRx = now;
319  m_endRx = now + rxDuration;
320  NS_ASSERT (IsStateRx ());
321 }
322 
323 void
325 {
326  NotifySwitchingStart (switchingDuration);
327  Time now = Simulator::Now ();
328  switch (GetState ())
329  {
330  case WifiPhy::RX:
331  /* The packet which is being received as well
332  * as its endRx event are cancelled by the caller.
333  */
334  m_rxing = false;
336  m_endRx = now;
337  break;
338  case WifiPhy::CCA_BUSY:
339  {
340  Time ccaStart = Max (m_endRx, m_endTx);
341  ccaStart = Max (ccaStart, m_startCcaBusy);
342  ccaStart = Max (ccaStart, m_endSwitching);
343  m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
344  } break;
345  case WifiPhy::IDLE:
347  break;
348  case WifiPhy::TX:
349  case WifiPhy::SWITCHING:
350  default:
351  NS_FATAL_ERROR ("Invalid WifiPhy state.");
352  break;
353  }
354 
355  if (now < m_endCcaBusy)
356  {
357  m_endCcaBusy = now;
358  }
359 
360  m_stateLogger (now, switchingDuration, WifiPhy::SWITCHING);
362  m_startSwitching = now;
363  m_endSwitching = now + switchingDuration;
365 }
366 
367 void
369 {
370  m_rxOkTrace (packet, snr, mode, preamble);
371  NotifyRxEndOk ();
372  DoSwitchFromRx ();
373  if (!m_rxOkCallback.IsNull ())
374  {
375  m_rxOkCallback (packet, snr, mode, preamble);
376  }
377 
378 }
379 void
381 {
382  m_rxErrorTrace (packet, snr);
383  NotifyRxEndError ();
384  DoSwitchFromRx ();
385  if (!m_rxErrorCallback.IsNull ())
386  {
387  m_rxErrorCallback (packet, snr);
388  }
389 }
390 
391 void
393 {
394  NS_ASSERT (IsStateRx ());
395  NS_ASSERT (m_rxing);
396 
397  Time now = Simulator::Now ();
400  m_rxing = false;
401 
403 }
404 void
406 {
407  NotifyMaybeCcaBusyStart (duration);
408  Time now = Simulator::Now ();
409  switch (GetState ())
410  {
411  case WifiPhy::SWITCHING:
412  break;
413  case WifiPhy::IDLE:
415  break;
416  case WifiPhy::CCA_BUSY:
417  break;
418  case WifiPhy::RX:
419  break;
420  case WifiPhy::TX:
421  break;
422  }
423  if (GetState () != WifiPhy::CCA_BUSY)
424  {
425  m_startCcaBusy = now;
426  }
427  m_endCcaBusy = std::max (m_endCcaBusy, now + duration);
428 }
429 
430 } // namespace ns3
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
void DoSwitchFromRx(void)
Switch the state from RX.
Time GetStateDuration(void)
Return the elapsed time of the current state.
#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 the class in the ns-3 factory.
Definition: object-base.h:38
TracedCallback< Time, Time, enum WifiPhy::State > m_stateLogger
State
The state of the PHY layer.
Definition: wifi-phy.h:123
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1018
void SwitchToChannelSwitching(Time switchingDuration)
Switch state to channel switching for the given duration.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
void NotifyRxEndError(void)
Notify all WifiPhyListener that the reception was not successful.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
void SetReceiveOkCallback(WifiPhy::RxOkCallback callback)
Set a callback for a successful reception.
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:91
The PHY layer is switching to other channel.
Definition: wifi-phy.h:144
void SwitchToTx(Time txDuration, Ptr< const Packet > packet, WifiMode txMode, WifiPreamble preamble, uint8_t txPower)
Switch state to TX for the given duration.
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
Definition: wifi-preamble.h:29
bool IsStateIdle(void)
Check whether the current state is IDLE.
Time GetDelayUntilIdle(void)
Return the time before the state is back to IDLE.
TracedCallback< Ptr< const Packet >, double, WifiMode, enum WifiPreamble > m_rxOkTrace
bool IsStateSwitching(void)
Check whether the current state is SWITCHING.
void NotifyTxStart(Time duration)
Notify all WifiPhyListener that the transmission has started for the given duration.
receive notifications about phy events.
Definition: wifi-phy.h:44
void NotifySwitchingStart(Time duration)
Notify all WifiPhyListener that we are switching channel with the given channel switching delay...
bool IsStateRx(void)
Check whether the current state is RX.
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:204
void SetReceiveErrorCallback(WifiPhy::RxErrorCallback callback)
Set a callback for a failed reception.
void NotifyMaybeCcaBusyStart(Time duration)
Notify all WifiPhyListener that the CCA has started for the given duration.
WifiPhy::RxErrorCallback m_rxErrorCallback
The PHY layer is IDLE.
Definition: wifi-phy.h:128
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
void SwitchFromRxEndError(Ptr< const Packet > packet, double snr)
Switch from RX after the reception failed.
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
void NotifyRxEndOk(void)
Notify all WifiPhyListener that the reception was successful.
void SwitchFromRxEndOk(Ptr< Packet > packet, double snr, WifiMode mode, enum WifiPreamble preamble)
Switch from RX after the reception was successful.
static TypeId GetTypeId(void)
enum WifiPhy::State GetState(void)
Return the current state of WifiPhy.
bool IsStateBusy(void)
Check whether the current state is not IDLE.
bool IsStateCcaBusy(void)
Check whether the current state is CCA busy.
TracedCallback< Ptr< const Packet >, WifiMode, WifiPreamble, uint8_t > m_txTrace
TracedCallback< Ptr< const Packet >, double > m_rxErrorTrace
bool IsStateTx(void)
Check whether the current state is TX.
a base class which provides memory management and object aggregation
Definition: object.h:64
void SwitchToRx(Time rxDuration)
Switch state to RX for the given duration.
void LogPreviousIdleAndCcaBusyStates(void)
Log the ideal and CCA states.
Time GetLastRxStartTime(void) const
Return the time the last RX start.
The PHY layer is receiving a packet.
Definition: wifi-phy.h:140
void NotifyRxStart(Time duration)
Notify all WifiPhyListener that the reception has started for the given duration. ...
The PHY layer has sense the medium busy through the CCA mechanism.
Definition: wifi-phy.h:132
a unique identifier for an interface.
Definition: type-id.h:49
The PHY layer is sending a packet.
Definition: wifi-phy.h:136
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
void RegisterListener(WifiPhyListener *listener)
Register WifiPhyListener to this WifiPhyStateHelper.
void SwitchMaybeToCcaBusy(Time duration)
Switch to CCA busy.
WifiPhy::RxOkCallback m_rxOkCallback