A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
wifi-phy-state-helper.cc
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
32 WifiPhyStateHelper::GetTypeId (void)
33 {
34  static TypeId tid = TypeId ("ns3::WifiPhyStateHelper")
35  .SetParent<Object> ()
36  .AddConstructor<WifiPhyStateHelper> ()
37  .AddTraceSource ("State",
38  "The state of the PHY layer",
39  MakeTraceSourceAccessor (&WifiPhyStateHelper::m_stateLogger))
40  .AddTraceSource ("RxOk",
41  "A packet has been received successfully.",
42  MakeTraceSourceAccessor (&WifiPhyStateHelper::m_rxOkTrace))
43  .AddTraceSource ("RxError",
44  "A packet has been received unsuccessfully.",
45  MakeTraceSourceAccessor (&WifiPhyStateHelper::m_rxErrorTrace))
46  .AddTraceSource ("Tx", "Packet transmission is starting.",
47  MakeTraceSourceAccessor (&WifiPhyStateHelper::m_txTrace))
48  ;
49  return tid;
50 }
51 
52 WifiPhyStateHelper::WifiPhyStateHelper ()
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_endSensing (Seconds (0)),
59  m_startTx (Seconds (0)),
60  m_startRx (Seconds (0)),
61  m_startCcaBusy (Seconds (0)),
62  m_startSwitching (Seconds (0)),
63  m_startSensing (Seconds (0)),
64  m_previousStateChangeTime (Seconds (0))
65 {
66  NS_LOG_FUNCTION (this);
67 }
68 
69 void
70 WifiPhyStateHelper::SetReceiveOkCallback (WifiPhy::RxOkCallback callback)
71 {
72  m_rxOkCallback = callback;
73 }
74 void
75 WifiPhyStateHelper::SetReceiveErrorCallback (WifiPhy::RxErrorCallback callback)
76 {
77  m_rxErrorCallback = callback;
78 }
79 void
80 WifiPhyStateHelper::RegisterListener (WifiPhyListener *listener)
81 {
82  m_listeners.push_back (listener);
83 }
84 
85 bool
86 WifiPhyStateHelper::IsStateIdle (void)
87 {
88  return (GetState () == WifiPhy::IDLE);
89 }
90 bool
91 WifiPhyStateHelper::IsStateBusy (void)
92 {
93  return (GetState () != WifiPhy::IDLE);
94 }
95 bool
96 WifiPhyStateHelper::IsStateCcaBusy (void)
97 {
98  return (GetState () == WifiPhy::CCA_BUSY);
99 }
100 bool
101 WifiPhyStateHelper::IsStateRx (void)
102 {
103  return (GetState () == WifiPhy::RX);
104 }
105 bool
106 WifiPhyStateHelper::IsStateTx (void)
107 {
108  return (GetState () == WifiPhy::TX);
109 }
110 bool
111 WifiPhyStateHelper::IsStateSwitching (void)
112 {
113  return (GetState () == WifiPhy::SWITCHING);
114 }
115 bool
116 WifiPhyStateHelper::IsStateSensing (void)
117 {
118  return (GetState () == WifiPhy::SENSING);
119 }
120 
121 
122 Time
123 WifiPhyStateHelper::GetStateDuration (void)
124 {
125  return Simulator::Now () - m_previousStateChangeTime;
126 }
127 
128 Time
129 WifiPhyStateHelper::GetDelayUntilIdle (void)
130 {
131  Time retval;
132 
133  switch (GetState ())
134  {
135  case WifiPhy::RX:
136  retval = m_endRx - Simulator::Now ();
137  break;
138  case WifiPhy::TX:
139  retval = m_endTx - Simulator::Now ();
140  break;
141  case WifiPhy::CCA_BUSY:
142  retval = m_endCcaBusy - Simulator::Now ();
143  break;
144  case WifiPhy::SWITCHING:
145  retval = m_endSwitching - Simulator::Now ();
146  break;
147  case WifiPhy::SENSING:
148  retval = m_endSensing - Simulator::Now ();
149  break;
150  case WifiPhy::IDLE:
151  retval = Seconds (0);
152  break;
153  default:
154  NS_FATAL_ERROR ("Invalid WifiPhy state.");
155  retval = Seconds (0);
156  break;
157  }
158  retval = Max (retval, Seconds (0));
159  return retval;
160 }
161 
162 Time
163 WifiPhyStateHelper::GetLastRxStartTime (void) const
164 {
165  return m_startRx;
166 }
167 
168 enum WifiPhy::State
169 WifiPhyStateHelper::GetState (void)
170 {
171  if (m_endTx > Simulator::Now ())
172  {
173  return WifiPhy::TX;
174  }
175  else if (m_rxing)
176  {
177  return WifiPhy::RX;
178  }
179  else if (m_endSwitching > Simulator::Now ())
180  {
181  return WifiPhy::SWITCHING;
182  }
183  else if (m_endSensing > Simulator::Now ())
184  {
185  return WifiPhy::SENSING;
186  }
187  else if (m_endCcaBusy > Simulator::Now ())
188  {
189  return WifiPhy::CCA_BUSY;
190  }
191  else
192  {
193  return WifiPhy::IDLE;
194  }
195 }
196 
197 
198 void
199 WifiPhyStateHelper::NotifyTxStart (Time duration)
200 {
201  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
202  {
203  (*i)->NotifyTxStart (duration);
204  }
205 }
206 void
207 WifiPhyStateHelper::NotifyRxStart (Time duration)
208 {
209  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
210  {
211  (*i)->NotifyRxStart (duration);
212  }
213 }
214 void
215 WifiPhyStateHelper::NotifyRxEndOk (void)
216 {
217  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
218  {
219  (*i)->NotifyRxEndOk ();
220  }
221 }
222 void
223 WifiPhyStateHelper::NotifyRxEndError (void)
224 {
225  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
226  {
227  (*i)->NotifyRxEndError ();
228  }
229 }
230 void
231 WifiPhyStateHelper::NotifyMaybeCcaBusyStart (Time duration)
232 {
233  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
234  {
235  (*i)->NotifyMaybeCcaBusyStart (duration);
236  }
237 }
238 void
239 WifiPhyStateHelper::NotifySwitchingStart (Time duration, uint16_t toChannel)
240 {
241  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
242  {
243  (*i)->NotifySwitchingStart (duration, toChannel);
244  }
245 }
246 void
247 WifiPhyStateHelper::NotifySensingStart (Time duration)
248 {
249  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
250  {
251  (*i)->NotifySensingStart (duration);
252  }
253 }
254 
255 void
256 WifiPhyStateHelper::LogPreviousIdleAndCcaBusyStates (void)
257 {
258  Time now = Simulator::Now ();
259  Time idleStart = Max (m_endCcaBusy, m_endRx);
260  idleStart = Max (idleStart, m_endTx);
261  idleStart = Max (idleStart, m_endSwitching);
262  idleStart = Max (idleStart, m_endSensing);
263  NS_ASSERT (idleStart <= now);
264  if (m_endCcaBusy > m_endRx
265  && m_endCcaBusy > m_endSwitching
266  && m_endCcaBusy > m_endTx
267  && m_endCcaBusy > m_endSensing)
268  {
269  Time ccaBusyStart = Max (m_endTx, m_endRx);
270  ccaBusyStart = Max (ccaBusyStart, m_startCcaBusy);
271  ccaBusyStart = Max (ccaBusyStart, m_endSwitching);
272  ccaBusyStart = Max (ccaBusyStart, m_endSensing);
273  m_stateLogger (ccaBusyStart, idleStart - ccaBusyStart, WifiPhy::CCA_BUSY);
274  }
275  m_stateLogger (idleStart, now - idleStart, WifiPhy::IDLE);
276 }
277 
278 void
279 WifiPhyStateHelper::SwitchToTx (Time txDuration, Ptr<const Packet> packet, WifiMode txMode,
280  WifiPreamble preamble, uint8_t txPower)
281 {
282  m_txTrace (packet, txMode, preamble, txPower);
283  NotifyTxStart (txDuration);
284  Time now = Simulator::Now ();
285  switch (GetState ())
286  {
287  case WifiPhy::RX:
288  /* The packet which is being received as well
289  * as its endRx event are cancelled by the caller.
290  */
291  m_rxing = false;
292  m_stateLogger (m_startRx, now - m_startRx, WifiPhy::RX);
293  m_endRx = now;
294  break;
295  case WifiPhy::CCA_BUSY:
296  {
297  Time ccaStart = Max (m_endRx, m_endTx);
298  ccaStart = Max (ccaStart, m_startCcaBusy);
299  ccaStart = Max (ccaStart, m_endSwitching);
300  ccaStart = Max (ccaStart, m_endSensing);
301  m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
302  } break;
303  case WifiPhy::IDLE:
304  LogPreviousIdleAndCcaBusyStates ();
305  break;
306  case WifiPhy::SWITCHING:
307  default:
308  NS_FATAL_ERROR ("Invalid WifiPhy state.");
309  break;
310  }
311  m_stateLogger (now, txDuration, WifiPhy::TX);
312  m_previousStateChangeTime = now;
313  m_endTx = now + txDuration;
314  m_startTx = now;
315 }
316 void
317 WifiPhyStateHelper::SwitchToRx (Time rxDuration)
318 {
319  NS_ASSERT (IsStateIdle () || IsStateCcaBusy ());
320  NS_ASSERT (!m_rxing);
321  NotifyRxStart (rxDuration);
322  Time now = Simulator::Now ();
323  switch (GetState ())
324  {
325  case WifiPhy::IDLE:
326  LogPreviousIdleAndCcaBusyStates ();
327  break;
328  case WifiPhy::CCA_BUSY:
329  {
330  Time ccaStart = Max (m_endRx, m_endTx);
331  ccaStart = Max (ccaStart, m_startCcaBusy);
332  ccaStart = Max (ccaStart, m_endSwitching);
333  ccaStart = Max (ccaStart, m_endSensing);
334  m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
335  } break;
336  case WifiPhy::SWITCHING:
337  case WifiPhy::SENSING:
338  case WifiPhy::RX:
339  case WifiPhy::TX:
340  NS_FATAL_ERROR ("Invalid WifiPhy state.");
341  break;
342  }
343  m_previousStateChangeTime = now;
344  m_rxing = true;
345  m_startRx = now;
346  m_endRx = now + rxDuration;
347  NS_ASSERT (IsStateRx ());
348 }
349 
350 void
351 WifiPhyStateHelper::SwitchToChannelSwitching (Time switchingDuration, uint16_t toChannel)
352 {
353  NotifySwitchingStart (switchingDuration, toChannel);
354  Time now = Simulator::Now ();
355  switch (GetState ())
356  {
357  case WifiPhy::RX:
358  /* The packet which is being received as well
359  * as its endRx event are cancelled by the caller.
360  */
361  m_rxing = false;
362  m_stateLogger (m_startRx, now - m_startRx, WifiPhy::RX);
363  m_endRx = now;
364  break;
365  case WifiPhy::CCA_BUSY:
366  {
367  Time ccaStart = Max (m_endRx, m_endTx);
368  ccaStart = Max (ccaStart, m_startCcaBusy);
369  ccaStart = Max (ccaStart, m_endSwitching);
370  ccaStart = Max (ccaStart, m_endSensing);
371  m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
372  } break;
373  case WifiPhy::IDLE:
374  LogPreviousIdleAndCcaBusyStates ();
375  break;
376  case WifiPhy::TX:
377  case WifiPhy::SWITCHING:
378  default:
379  NS_FATAL_ERROR ("Invalid WifiPhy state.");
380  break;
381  }
382 
383  if (now < m_endCcaBusy)
384  {
385  m_endCcaBusy = now;
386  }
387 
388  m_stateLogger (now, switchingDuration, WifiPhy::SWITCHING);
389  m_previousStateChangeTime = now;
390  m_startSwitching = now;
391  m_endSwitching = now + switchingDuration;
392  NS_ASSERT (IsStateSwitching ());
393 }
394 
395 void
396 WifiPhyStateHelper::SwitchToChannelSensing (Time sensingDuration)
397 {
398  NotifySensingStart (sensingDuration);
399  Time now = Simulator::Now ();
400  switch (GetState ())
401  {
402  case WifiPhy::RX:
403  /* The packet which is being received as well
404  * as its endRx event are cancelled by the caller.
405  */
406  m_rxing = false;
407  m_stateLogger (m_startRx, now - m_startRx, WifiPhy::RX);
408  m_endRx = now;
409  break;
410  case WifiPhy::CCA_BUSY:
411  {
412  Time ccaStart = Max (m_endRx, m_endTx);
413  ccaStart = Max (ccaStart, m_startCcaBusy);
414  ccaStart = Max (ccaStart, m_endSwitching);
415  ccaStart = Max (ccaStart, m_endSensing);
416  m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
417  } break;
418  case WifiPhy::IDLE:
419  LogPreviousIdleAndCcaBusyStates ();
420  break;
421  case WifiPhy::TX:
422  case WifiPhy::SWITCHING:
423  case WifiPhy::SENSING:
424  default:
425  NS_FATAL_ERROR ("Invalid WifiPhy state.");
426  break;
427  }
428 
429  if (now < m_endCcaBusy)
430  {
431  m_endCcaBusy = now;
432  }
433 
434  m_stateLogger (now, sensingDuration, WifiPhy::SENSING);
435  m_previousStateChangeTime = now;
436  m_startSensing = now;
437  m_endSensing = now + sensingDuration;
438  NS_ASSERT (IsStateSensing ());
439 }
440 
441 void
442 WifiPhyStateHelper::SwitchFromRxEndOk (Ptr<Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble)
443 {
444  m_rxOkTrace (packet, snr, mode, preamble);
445  NotifyRxEndOk ();
446  DoSwitchFromRx ();
447  if (!m_rxOkCallback.IsNull ())
448  {
449  m_rxOkCallback (packet, snr, mode, preamble);
450  }
451 
452 }
453 void
454 WifiPhyStateHelper::SwitchFromRxEndError (Ptr<const Packet> packet, double snr)
455 {
456  m_rxErrorTrace (packet, snr);
457  NotifyRxEndError ();
458  DoSwitchFromRx ();
459  if (!m_rxErrorCallback.IsNull ())
460  {
461  m_rxErrorCallback (packet, snr);
462  }
463 }
464 
465 void
466 WifiPhyStateHelper::DoSwitchFromRx (void)
467 {
468  NS_ASSERT (IsStateRx ());
469  NS_ASSERT (m_rxing);
470 
471  Time now = Simulator::Now ();
472  m_stateLogger (m_startRx, now - m_startRx, WifiPhy::RX);
473  m_previousStateChangeTime = now;
474  m_rxing = false;
475 
476  NS_ASSERT (IsStateIdle () || IsStateCcaBusy ());
477 }
478 void
479 WifiPhyStateHelper::SwitchMaybeToCcaBusy (Time duration)
480 {
481  NotifyMaybeCcaBusyStart (duration);
482  Time now = Simulator::Now ();
483  switch (GetState ())
484  {
485  case WifiPhy::SWITCHING:
486  case WifiPhy::SENSING:
487  break;
488  case WifiPhy::IDLE:
489  LogPreviousIdleAndCcaBusyStates ();
490  break;
491  case WifiPhy::CCA_BUSY:
492  break;
493  case WifiPhy::RX:
494  break;
495  case WifiPhy::TX:
496  break;
497  }
498  m_startCcaBusy = now;
499  m_endCcaBusy = std::max (m_endCcaBusy, now + duration);
500 }
501 
502 } // namespace ns3
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
WifiPreamble
Definition: wifi-preamble.h:29
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586