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 
32 TypeId
34 {
35  static TypeId tid = TypeId ("ns3::WifiPhyStateHelper")
36  .SetParent<Object> ()
37  .AddConstructor<WifiPhyStateHelper> ()
38  .AddTraceSource ("State",
39  "The state of the PHY layer",
41  .AddTraceSource ("RxOk",
42  "A packet has been received successfully.",
44  .AddTraceSource ("RxError",
45  "A packet has been received unsuccessfully.",
47  .AddTraceSource ("Tx", "Packet transmission is starting.",
49  ;
50  return tid;
51 }
52 
54  : m_rxing (false),
55  m_endTx (Seconds (0)),
56  m_endRx (Seconds (0)),
57  m_endCcaBusy (Seconds (0)),
58  m_endSwitching (Seconds (0)),
59  m_startTx (Seconds (0)),
60  m_startRx (Seconds (0)),
61  m_startCcaBusy (Seconds (0)),
62  m_startSwitching (Seconds (0)),
63  m_previousStateChangeTime (Seconds (0))
64 {
65  NS_LOG_FUNCTION (this);
66 }
67 
68 void
70 {
71  m_rxOkCallback = callback;
72 }
73 void
75 {
76  m_rxErrorCallback = callback;
77 }
78 void
80 {
81  m_listeners.push_back (listener);
82 }
83 
84 bool
86 {
87  return (GetState () == WifiPhy::IDLE);
88 }
89 bool
91 {
92  return (GetState () != WifiPhy::IDLE);
93 }
94 bool
96 {
97  return (GetState () == WifiPhy::CCA_BUSY);
98 }
99 bool
101 {
102  return (GetState () == WifiPhy::RX);
103 }
104 bool
106 {
107  return (GetState () == WifiPhy::TX);
108 }
109 bool
111 {
112  return (GetState () == WifiPhy::SWITCHING);
113 }
114 
115 
116 
117 Time
119 {
121 }
122 
123 Time
125 {
126  Time retval;
127 
128  switch (GetState ())
129  {
130  case WifiPhy::RX:
131  retval = m_endRx - Simulator::Now ();
132  break;
133  case WifiPhy::TX:
134  retval = m_endTx - Simulator::Now ();
135  break;
136  case WifiPhy::CCA_BUSY:
137  retval = m_endCcaBusy - Simulator::Now ();
138  break;
139  case WifiPhy::SWITCHING:
140  retval = m_endSwitching - Simulator::Now ();
141  break;
142  case WifiPhy::IDLE:
143  retval = Seconds (0);
144  break;
145  default:
146  NS_FATAL_ERROR ("Invalid WifiPhy state.");
147  retval = Seconds (0);
148  break;
149  }
150  retval = Max (retval, Seconds (0));
151  return retval;
152 }
153 
154 Time
156 {
157  return m_startRx;
158 }
159 
160 enum WifiPhy::State
162 {
163  if (m_endTx > Simulator::Now ())
164  {
165  return WifiPhy::TX;
166  }
167  else if (m_rxing)
168  {
169  return WifiPhy::RX;
170  }
171  else if (m_endSwitching > Simulator::Now ())
172  {
173  return WifiPhy::SWITCHING;
174  }
175  else if (m_endCcaBusy > Simulator::Now ())
176  {
177  return WifiPhy::CCA_BUSY;
178  }
179  else
180  {
181  return WifiPhy::IDLE;
182  }
183 }
184 
185 
186 void
188 {
189  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
190  {
191  (*i)->NotifyTxStart (duration);
192  }
193 }
194 void
196 {
197  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
198  {
199  (*i)->NotifyRxStart (duration);
200  }
201 }
202 void
204 {
205  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
206  {
207  (*i)->NotifyRxEndOk ();
208  }
209 }
210 void
212 {
213  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
214  {
215  (*i)->NotifyRxEndError ();
216  }
217 }
218 void
220 {
221  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
222  {
223  (*i)->NotifyMaybeCcaBusyStart (duration);
224  }
225 }
226 void
228 {
229  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
230  {
231  (*i)->NotifySwitchingStart (duration);
232  }
233 }
234 
235 void
237 {
238  Time now = Simulator::Now ();
239  Time idleStart = Max (m_endCcaBusy, m_endRx);
240  idleStart = Max (idleStart, m_endTx);
241  idleStart = Max (idleStart, m_endSwitching);
242  NS_ASSERT (idleStart <= now);
243  if (m_endCcaBusy > m_endRx
245  && m_endCcaBusy > m_endTx)
246  {
247  Time ccaBusyStart = Max (m_endTx, m_endRx);
248  ccaBusyStart = Max (ccaBusyStart, m_startCcaBusy);
249  ccaBusyStart = Max (ccaBusyStart, m_endSwitching);
250  m_stateLogger (ccaBusyStart, idleStart - ccaBusyStart, WifiPhy::CCA_BUSY);
251  }
252  m_stateLogger (idleStart, now - idleStart, WifiPhy::IDLE);
253 }
254 
255 void
257  WifiPreamble preamble, uint8_t txPower)
258 {
259  m_txTrace (packet, txMode, preamble, txPower);
260  NotifyTxStart (txDuration);
261  Time now = Simulator::Now ();
262  switch (GetState ())
263  {
264  case WifiPhy::RX:
265  /* The packet which is being received as well
266  * as its endRx event are cancelled by the caller.
267  */
268  m_rxing = false;
270  m_endRx = now;
271  break;
272  case WifiPhy::CCA_BUSY:
273  {
274  Time ccaStart = Max (m_endRx, m_endTx);
275  ccaStart = Max (ccaStart, m_startCcaBusy);
276  ccaStart = Max (ccaStart, m_endSwitching);
277  m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
278  } break;
279  case WifiPhy::IDLE:
281  break;
282  case WifiPhy::SWITCHING:
283  default:
284  NS_FATAL_ERROR ("Invalid WifiPhy state.");
285  break;
286  }
287  m_stateLogger (now, txDuration, WifiPhy::TX);
289  m_endTx = now + txDuration;
290  m_startTx = now;
291 }
292 void
294 {
296  NS_ASSERT (!m_rxing);
297  NotifyRxStart (rxDuration);
298  Time now = Simulator::Now ();
299  switch (GetState ())
300  {
301  case WifiPhy::IDLE:
303  break;
304  case WifiPhy::CCA_BUSY:
305  {
306  Time ccaStart = Max (m_endRx, m_endTx);
307  ccaStart = Max (ccaStart, m_startCcaBusy);
308  ccaStart = Max (ccaStart, m_endSwitching);
309  m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
310  } break;
311  case WifiPhy::SWITCHING:
312  case WifiPhy::RX:
313  case WifiPhy::TX:
314  NS_FATAL_ERROR ("Invalid WifiPhy state.");
315  break;
316  }
318  m_rxing = true;
319  m_startRx = now;
320  m_endRx = now + rxDuration;
321  NS_ASSERT (IsStateRx ());
322 }
323 
324 void
326 {
327  NotifySwitchingStart (switchingDuration);
328  Time now = Simulator::Now ();
329  switch (GetState ())
330  {
331  case WifiPhy::RX:
332  /* The packet which is being received as well
333  * as its endRx event are cancelled by the caller.
334  */
335  m_rxing = false;
337  m_endRx = now;
338  break;
339  case WifiPhy::CCA_BUSY:
340  {
341  Time ccaStart = Max (m_endRx, m_endTx);
342  ccaStart = Max (ccaStart, m_startCcaBusy);
343  ccaStart = Max (ccaStart, m_endSwitching);
344  m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
345  } break;
346  case WifiPhy::IDLE:
348  break;
349  case WifiPhy::TX:
350  case WifiPhy::SWITCHING:
351  default:
352  NS_FATAL_ERROR ("Invalid WifiPhy state.");
353  break;
354  }
355 
356  if (now < m_endCcaBusy)
357  {
358  m_endCcaBusy = now;
359  }
360 
361  m_stateLogger (now, switchingDuration, WifiPhy::SWITCHING);
363  m_startSwitching = now;
364  m_endSwitching = now + switchingDuration;
366 }
367 
368 void
370 {
371  m_rxOkTrace (packet, snr, mode, preamble);
372  NotifyRxEndOk ();
373  DoSwitchFromRx ();
374  if (!m_rxOkCallback.IsNull ())
375  {
376  m_rxOkCallback (packet, snr, mode, preamble);
377  }
378 
379 }
380 void
382 {
383  m_rxErrorTrace (packet, snr);
384  NotifyRxEndError ();
385  DoSwitchFromRx ();
386  if (!m_rxErrorCallback.IsNull ())
387  {
388  m_rxErrorCallback (packet, snr);
389  }
390 }
391 
392 void
394 {
395  NS_ASSERT (IsStateRx ());
396  NS_ASSERT (m_rxing);
397 
398  Time now = Simulator::Now ();
401  m_rxing = false;
402 
404 }
405 void
407 {
408  NotifyMaybeCcaBusyStart (duration);
409  Time now = Simulator::Now ();
410  switch (GetState ())
411  {
412  case WifiPhy::SWITCHING:
413  break;
414  case WifiPhy::IDLE:
416  break;
417  case WifiPhy::CCA_BUSY:
418  break;
419  case WifiPhy::RX:
420  break;
421  case WifiPhy::TX:
422  break;
423  }
424  if (GetState () != WifiPhy::CCA_BUSY)
425  {
426  m_startCcaBusy = now;
427  }
428  m_endCcaBusy = std::max (m_endCcaBusy, now + duration);
429 }
430 
431 } // namespace ns3
keep track of time values and allow control of global simulation resolution
Definition: nstime.h:81
void DoSwitchFromRx(void)
Switch the state from RX.
Time GetStateDuration(void)
Return the elapsed time of the current state.
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:345
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:1014
void SwitchToChannelSwitching(Time switchingDuration)
Switch state to channel switching for the given duration.
#define NS_ASSERT(condition)
Definition: assert.h:64
void NotifyRxEndError(void)
Notify all WifiPhyListener that the reception was not successful.
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
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
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
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.
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
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Definition: int64x64.h:95
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)
NS_LOG_COMPONENT_DEFINE("WifiPhyStateHelper")
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:63
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:611
void RegisterListener(WifiPhyListener *listener)
Register WifiPhyListener to this WifiPhyStateHelper.
void SwitchMaybeToCcaBusy(Time duration)
Switch to CCA busy.
WifiPhy::RxOkCallback m_rxOkCallback