A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
yans-wifi-phy.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 "yans-wifi-phy.h"
22 #include "yans-wifi-channel.h"
23 #include "wifi-mode.h"
24 #include "wifi-preamble.h"
25 #include "wifi-phy-state-helper.h"
26 #include "error-rate-model.h"
27 #include "ns3/simulator.h"
28 #include "ns3/packet.h"
29 #include "ns3/assert.h"
30 #include "ns3/log.h"
31 #include "ns3/double.h"
32 #include "ns3/uinteger.h"
33 #include "ns3/enum.h"
34 #include "ns3/pointer.h"
35 #include "ns3/net-device.h"
36 #include "ns3/trace-source-accessor.h"
37 #include <cmath>
38 
39 NS_LOG_COMPONENT_DEFINE ("YansWifiPhy");
40 
41 namespace ns3 {
42 
43 NS_OBJECT_ENSURE_REGISTERED (YansWifiPhy);
44 
45 TypeId
47 {
48  static TypeId tid = TypeId ("ns3::YansWifiPhy")
49  .SetParent<WifiPhy> ()
50  .AddConstructor<YansWifiPhy> ()
51  .AddAttribute ("EnergyDetectionThreshold",
52  "The energy of a received signal should be higher than "
53  "this threshold (dbm) to allow the PHY layer to detect the signal.",
54  DoubleValue (-96.0),
55  MakeDoubleAccessor (&YansWifiPhy::SetEdThreshold,
57  MakeDoubleChecker<double> ())
58  .AddAttribute ("CcaMode1Threshold",
59  "The energy of a received signal should be higher than "
60  "this threshold (dbm) to allow the PHY layer to declare CCA BUSY state",
61  DoubleValue (-99.0),
62  MakeDoubleAccessor (&YansWifiPhy::SetCcaMode1Threshold,
64  MakeDoubleChecker<double> ())
65  .AddAttribute ("TxGain",
66  "Transmission gain (dB).",
67  DoubleValue (1.0),
68  MakeDoubleAccessor (&YansWifiPhy::SetTxGain,
70  MakeDoubleChecker<double> ())
71  .AddAttribute ("RxGain",
72  "Reception gain (dB).",
73  DoubleValue (1.0),
74  MakeDoubleAccessor (&YansWifiPhy::SetRxGain,
76  MakeDoubleChecker<double> ())
77  .AddAttribute ("TxPowerLevels",
78  "Number of transmission power levels available between "
79  "TxPowerStart and TxPowerEnd included.",
80  UintegerValue (1),
81  MakeUintegerAccessor (&YansWifiPhy::m_nTxPower),
82  MakeUintegerChecker<uint32_t> ())
83  .AddAttribute ("TxPowerEnd",
84  "Maximum available transmission level (dbm).",
85  DoubleValue (16.0206),
86  MakeDoubleAccessor (&YansWifiPhy::SetTxPowerEnd,
88  MakeDoubleChecker<double> ())
89  .AddAttribute ("TxPowerStart",
90  "Minimum available transmission level (dbm).",
91  DoubleValue (16.0206),
92  MakeDoubleAccessor (&YansWifiPhy::SetTxPowerStart,
94  MakeDoubleChecker<double> ())
95  .AddAttribute ("RxNoiseFigure",
96  "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver."
97  " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_figure), this is "
98  "\"the difference in decibels (dB) between"
99  " the noise output of the actual receiver to the noise output of an "
100  " ideal receiver with the same overall gain and bandwidth when the receivers "
101  " are connected to sources at the standard noise temperature T0 (usually 290 K)\"."
102  " For",
103  DoubleValue (7),
104  MakeDoubleAccessor (&YansWifiPhy::SetRxNoiseFigure,
106  MakeDoubleChecker<double> ())
107  .AddAttribute ("State", "The state of the PHY layer",
108  PointerValue (),
109  MakePointerAccessor (&YansWifiPhy::m_state),
110  MakePointerChecker<WifiPhyStateHelper> ())
111  .AddAttribute ("ChannelSwitchDelay",
112  "Delay between two short frames transmitted on different frequencies. NOTE: Unused now.",
113  TimeValue (MicroSeconds (250)),
114  MakeTimeAccessor (&YansWifiPhy::m_channelSwitchDelay),
115  MakeTimeChecker ())
116  .AddAttribute ("ChannelNumber",
117  "Channel center frequency = Channel starting frequency + 5 MHz * (nch - 1)",
118  UintegerValue (1),
119  MakeUintegerAccessor (&YansWifiPhy::SetChannelNumber,
121  MakeUintegerChecker<uint16_t> ())
122 
123  ;
124  return tid;
125 }
126 
128  : m_channelNumber (1),
129  m_endRxEvent (),
130  m_channelStartingFrequency (0)
131 {
132  NS_LOG_FUNCTION (this);
133  m_random = CreateObject<UniformRandomVariable> ();
134  m_state = CreateObject<WifiPhyStateHelper> ();
135 }
136 
138 {
139  NS_LOG_FUNCTION (this);
140 }
141 
142 void
144 {
145  NS_LOG_FUNCTION (this);
146  m_channel = 0;
147  m_deviceRateSet.clear ();
148  m_device = 0;
149  m_mobility = 0;
150  m_state = 0;
151 }
152 
153 void
155 {
156  NS_LOG_FUNCTION (this << standard);
157  switch (standard)
158  {
160  Configure80211a ();
161  break;
163  Configure80211b ();
164  break;
166  Configure80211g ();
167  break;
170  break;
173  break;
175  ConfigureHolland ();
176  break;
179  break;
182  break;
183  default:
184  NS_ASSERT (false);
185  break;
186  }
187 }
188 
189 
190 void
191 YansWifiPhy::SetRxNoiseFigure (double noiseFigureDb)
192 {
193  NS_LOG_FUNCTION (this << noiseFigureDb);
194  m_interference.SetNoiseFigure (DbToRatio (noiseFigureDb));
195 }
196 void
198 {
199  NS_LOG_FUNCTION (this << start);
201 }
202 void
204 {
205  NS_LOG_FUNCTION (this << end);
206  m_txPowerEndDbm = end;
207 }
208 void
210 {
211  NS_LOG_FUNCTION (this << n);
212  m_nTxPower = n;
213 }
214 void
216 {
217  NS_LOG_FUNCTION (this << gain);
218  m_txGainDb = gain;
219 }
220 void
222 {
223  NS_LOG_FUNCTION (this << gain);
224  m_rxGainDb = gain;
225 }
226 void
227 YansWifiPhy::SetEdThreshold (double threshold)
228 {
229  NS_LOG_FUNCTION (this << threshold);
230  m_edThresholdW = DbmToW (threshold);
231 }
232 void
234 {
235  NS_LOG_FUNCTION (this << threshold);
236  m_ccaMode1ThresholdW = DbmToW (threshold);
237 }
238 void
240 {
242 }
243 void
245 {
246  m_device = device;
247 }
248 void
250 {
251  m_mobility = mobility;
252 }
253 
254 double
256 {
258 }
259 double
261 {
262  return m_txPowerBaseDbm;
263 }
264 double
266 {
267  return m_txPowerEndDbm;
268 }
269 double
271 {
272  return m_txGainDb;
273 }
274 double
276 {
277  return m_rxGainDb;
278 }
279 
280 double
282 {
283  return WToDbm (m_edThresholdW);
284 }
285 
286 double
288 {
289  return WToDbm (m_ccaMode1ThresholdW);
290 }
291 
294 {
296 }
299 {
300  return m_device;
301 }
304 {
305  return m_mobility;
306 }
307 
308 double
309 YansWifiPhy::CalculateSnr (WifiMode txMode, double ber) const
310 {
311  return m_interference.GetErrorRateModel ()->CalculateSnr (txMode, ber);
312 }
313 
316 {
317  return m_channel;
318 }
319 void
321 {
322  m_channel = channel;
323  m_channel->Add (this);
324 }
325 
326 void
328 {
329  if (Simulator::Now () == Seconds (0))
330  {
331  // this is not channel switch, this is initialization
332  NS_LOG_DEBUG ("start at channel " << nch);
333  m_channelNumber = nch;
334  return;
335  }
336 
338  switch (m_state->GetState ())
339  {
340  case YansWifiPhy::RX:
341  NS_LOG_DEBUG ("drop packet because of channel switching while reception");
342  m_endRxEvent.Cancel ();
343  goto switchChannel;
344  break;
345  case YansWifiPhy::TX:
346  NS_LOG_DEBUG ("channel switching postponed until end of current transmission");
348  break;
350  case YansWifiPhy::IDLE:
351  goto switchChannel;
352  break;
353  default:
354  NS_ASSERT (false);
355  break;
356  }
357 
358  return;
359 
360 switchChannel:
361 
362  NS_LOG_DEBUG ("switching channel " << m_channelNumber << " -> " << nch);
365  /*
366  * Needed here to be able to correctly sensed the medium for the first
367  * time after the switching. The actual switching is not performed until
368  * after m_channelSwitchDelay. Packets received during the switching
369  * state are added to the event list and are employed later to figure
370  * out the state of the medium after the switching.
371  */
372  m_channelNumber = nch;
373 }
374 
375 uint16_t
377 {
378  return m_channelNumber;
379 }
380 
381 double
383 {
385 }
386 
387 void
389 {
390  m_state->SetReceiveOkCallback (callback);
391 }
392 void
394 {
395  m_state->SetReceiveErrorCallback (callback);
396 }
397 void
399  double rxPowerDbm,
400  WifiMode txMode,
401  enum WifiPreamble preamble)
402 {
403  NS_LOG_FUNCTION (this << packet << rxPowerDbm << txMode << preamble);
404  rxPowerDbm += m_rxGainDb;
405  double rxPowerW = DbmToW (rxPowerDbm);
406  Time rxDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble);
407  Time endRx = Simulator::Now () + rxDuration;
408 
410  event = m_interference.Add (packet->GetSize (),
411  txMode,
412  preamble,
413  rxDuration,
414  rxPowerW);
415 
416  switch (m_state->GetState ())
417  {
419  NS_LOG_DEBUG ("drop packet because of channel switching");
420  NotifyRxDrop (packet);
421  /*
422  * Packets received on the upcoming channel are added to the event list
423  * during the switching state. This way the medium can be correctly sensed
424  * when the device listens to the channel for the first time after the
425  * switching e.g. after channel switching, the channel may be sensed as
426  * busy due to other devices' tramissions started before the end of
427  * the switching.
428  */
429  if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ())
430  {
431  // that packet will be noise _after_ the completion of the
432  // channel switching.
433  goto maybeCcaBusy;
434  }
435  break;
436  case YansWifiPhy::RX:
437  NS_LOG_DEBUG ("drop packet because already in Rx (power=" <<
438  rxPowerW << "W)");
439  NotifyRxDrop (packet);
440  if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ())
441  {
442  // that packet will be noise _after_ the reception of the
443  // currently-received packet.
444  goto maybeCcaBusy;
445  }
446  break;
447  case YansWifiPhy::TX:
448  NS_LOG_DEBUG ("drop packet because already in Tx (power=" <<
449  rxPowerW << "W)");
450  NotifyRxDrop (packet);
451  if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ())
452  {
453  // that packet will be noise _after_ the transmission of the
454  // currently-transmitted packet.
455  goto maybeCcaBusy;
456  }
457  break;
459  case YansWifiPhy::IDLE:
460  if (rxPowerW > m_edThresholdW)
461  {
462  NS_LOG_DEBUG ("sync to signal (power=" << rxPowerW << "W)");
463  // sync to signal
464  m_state->SwitchToRx (rxDuration);
466  NotifyRxBegin (packet);
469  packet,
470  event);
471  }
472  else
473  {
474  NS_LOG_DEBUG ("drop packet because signal power too Small (" <<
475  rxPowerW << "<" << m_edThresholdW << ")");
476  NotifyRxDrop (packet);
477  goto maybeCcaBusy;
478  }
479  break;
480  }
481 
482  return;
483 
484 maybeCcaBusy:
485  // We are here because we have received the first bit of a packet and we are
486  // not going to be able to synchronize on it
487  // In this model, CCA becomes busy when the aggregation of all signals as
488  // tracked by the InterferenceHelper class is higher than the CcaBusyThreshold
489 
491  if (!delayUntilCcaEnd.IsZero ())
492  {
493  m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd);
494  }
495 }
496 
497 void
498 YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiMode txMode, WifiPreamble preamble, uint8_t txPower)
499 {
500  NS_LOG_FUNCTION (this << packet << txMode << preamble << (uint32_t)txPower);
501  /* Transmission can happen if:
502  * - we are syncing on a packet. It is the responsability of the
503  * MAC layer to avoid doing this but the PHY does nothing to
504  * prevent it.
505  * - we are idle
506  */
508 
509  Time txDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble);
510  if (m_state->IsStateRx ())
511  {
512  m_endRxEvent.Cancel ();
514  }
515  NotifyTxBegin (packet);
516  uint32_t dataRate500KbpsUnits = txMode.GetDataRate () / 500000;
517  bool isShortPreamble = (WIFI_PREAMBLE_SHORT == preamble);
518  NotifyMonitorSniffTx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, isShortPreamble);
519  m_state->SwitchToTx (txDuration, packet, txMode, preamble, txPower);
520  m_channel->Send (this, packet, GetPowerDbm (txPower) + m_txGainDb, txMode, preamble);
521 }
522 
523 uint32_t
525 {
526  return m_deviceRateSet.size ();
527 }
528 WifiMode
529 YansWifiPhy::GetMode (uint32_t mode) const
530 {
531  return m_deviceRateSet[mode];
532 }
533 uint32_t
535 {
536  return m_nTxPower;
537 }
538 
539 void
541 {
542  NS_LOG_FUNCTION (this);
543  m_channelStartingFrequency = 5e3; // 5.000 GHz
544 
553 }
554 
555 
556 void
558 {
559  NS_LOG_FUNCTION (this);
560  m_channelStartingFrequency = 2407; // 2.407 GHz
561 
566 }
567 
568 void
570 {
571  NS_LOG_FUNCTION (this);
572  m_channelStartingFrequency = 2407; // 2.407 GHz
573 
586 }
587 
588 void
590 {
591  NS_LOG_FUNCTION (this);
592  m_channelStartingFrequency = 5e3; // 5.000 GHz, suppose 802.11a
593 
602 }
603 
604 void
606 {
607  NS_LOG_FUNCTION (this);
608  m_channelStartingFrequency = 5e3; // 5.000 GHz, suppose 802.11a
609 
618 }
619 
620 void
622 {
623  NS_LOG_FUNCTION (this);
624  m_channelStartingFrequency = 5e3; // 5.000 GHz
630 }
631 
632 void
634 {
635  NS_LOG_FUNCTION (this);
636  m_channelStartingFrequency = 5e3; // 802.11p works over the 5Ghz freq range
637 
646 }
647 
648 void
650 {
651  NS_LOG_FUNCTION (this);
652  m_channelStartingFrequency = 5e3; // 802.11p works over the 5Ghz freq range
653 
662 }
663 
664 void
666 {
667  m_state->RegisterListener (listener);
668 }
669 
670 bool
672 {
673  return m_state->IsStateCcaBusy ();
674 }
675 
676 bool
678 {
679  return m_state->IsStateIdle ();
680 }
681 bool
683 {
684  return m_state->IsStateBusy ();
685 }
686 bool
688 {
689  return m_state->IsStateRx ();
690 }
691 bool
693 {
694  return m_state->IsStateTx ();
695 }
696 bool
698 {
699  return m_state->IsStateSwitching ();
700 }
701 
702 Time
704 {
705  return m_state->GetStateDuration ();
706 }
707 Time
709 {
710  return m_state->GetDelayUntilIdle ();
711 }
712 
713 Time
715 {
716  return m_state->GetLastRxStartTime ();
717 }
718 
719 double
720 YansWifiPhy::DbToRatio (double dB) const
721 {
722  double ratio = std::pow (10.0, dB / 10.0);
723  return ratio;
724 }
725 
726 double
727 YansWifiPhy::DbmToW (double dBm) const
728 {
729  double mW = std::pow (10.0, dBm / 10.0);
730  return mW / 1000.0;
731 }
732 
733 double
734 YansWifiPhy::WToDbm (double w) const
735 {
736  return 10.0 * std::log10 (w * 1000.0);
737 }
738 
739 double
740 YansWifiPhy::RatioToDb (double ratio) const
741 {
742  return 10.0 * std::log10 (ratio);
743 }
744 
745 double
747 {
748  return m_edThresholdW;
749 }
750 
751 double
752 YansWifiPhy::GetPowerDbm (uint8_t power) const
753 {
755  NS_ASSERT (m_nTxPower > 0);
756  double dbm;
757  if (m_nTxPower > 1)
758  {
759  dbm = m_txPowerBaseDbm + power * (m_txPowerEndDbm - m_txPowerBaseDbm) / (m_nTxPower - 1);
760  }
761  else
762  {
763  NS_ASSERT_MSG (m_txPowerBaseDbm == m_txPowerEndDbm, "cannot have TxPowerEnd != TxPowerStart with TxPowerLevels == 1");
764  dbm = m_txPowerBaseDbm;
765  }
766  return dbm;
767 }
768 
769 void
771 {
772  NS_LOG_FUNCTION (this << packet << event);
773  NS_ASSERT (IsStateRx ());
774  NS_ASSERT (event->GetEndTime () == Simulator::Now ());
775 
776  struct InterferenceHelper::SnrPer snrPer;
777  snrPer = m_interference.CalculateSnrPer (event);
779 
780  NS_LOG_DEBUG ("mode=" << (event->GetPayloadMode ().GetDataRate ()) <<
781  ", snr=" << snrPer.snr << ", per=" << snrPer.per << ", size=" << packet->GetSize ());
782  if (m_random->GetValue () > snrPer.per)
783  {
784  NotifyRxEnd (packet);
785  uint32_t dataRate500KbpsUnits = event->GetPayloadMode ().GetDataRate () / 500000;
786  bool isShortPreamble = (WIFI_PREAMBLE_SHORT == event->GetPreambleType ());
787  double signalDbm = RatioToDb (event->GetRxPowerW ()) + 30;
788  double noiseDbm = RatioToDb (event->GetRxPowerW () / snrPer.snr) - GetRxNoiseFigure () + 30;
789  NotifyMonitorSniffRx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, isShortPreamble, signalDbm, noiseDbm);
790  m_state->SwitchFromRxEndOk (packet, snrPer.snr, event->GetPayloadMode (), event->GetPreambleType ());
791  }
792  else
793  {
794  /* failure. */
795  NotifyRxDrop (packet);
796  m_state->SwitchFromRxEndError (packet, snrPer.snr);
797  }
798 }
799 
800 int64_t
802 {
803  NS_LOG_FUNCTION (this << stream);
804  m_random->SetStream (stream);
805  return 1;
806 }
807 } // namespace ns3