ChannelNumber attribute added to YansWifiPhy. Now it is possible to setup wifi channel using WifiPhyHelper::Set() method.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
3 * Copyright (c) 2005,2006 INRIA
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;
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.
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
18 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
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/random-variable.h"
30 #include "ns3/assert.h"
32 #include "ns3/double.h"
33 #include "ns3/uinteger.h"
35 #include "ns3/pointer.h"
36 #include "ns3/net-device.h"
37 #include "ns3/trace-source-accessor.h"
40 NS_LOG_COMPONENT_DEFINE ("YansWifiPhy");
44 NS_OBJECT_ENSURE_REGISTERED (YansWifiPhy);
47 YansWifiPhy::GetTypeId (void)
49 static TypeId tid = TypeId ("ns3::YansWifiPhy")
50 .SetParent<WifiPhy> ()
51 .AddConstructor<YansWifiPhy> ()
52 .AddAttribute ("EnergyDetectionThreshold",
53 "The energy of a received signal should be higher than "
54 "this threshold (dbm) to allow the PHY layer to detect the signal.",
56 MakeDoubleAccessor (&YansWifiPhy::SetEdThreshold,
57 &YansWifiPhy::GetEdThreshold),
58 MakeDoubleChecker<double> ())
59 .AddAttribute ("CcaMode1Threshold",
60 "The energy of a received signal should be higher than "
61 "this threshold (dbm) to allow the PHY layer to declare CCA BUSY state",
63 MakeDoubleAccessor (&YansWifiPhy::SetCcaMode1Threshold,
64 &YansWifiPhy::GetCcaMode1Threshold),
65 MakeDoubleChecker<double> ())
66 .AddAttribute ("TxGain",
67 "Transmission gain (dB).",
69 MakeDoubleAccessor (&YansWifiPhy::SetTxGain,
70 &YansWifiPhy::GetTxGain),
71 MakeDoubleChecker<double> ())
72 .AddAttribute ("RxGain",
73 "Reception gain (dB).",
75 MakeDoubleAccessor (&YansWifiPhy::SetRxGain,
76 &YansWifiPhy::GetRxGain),
77 MakeDoubleChecker<double> ())
78 .AddAttribute ("TxPowerLevels",
79 "Number of transmission power levels available between "
80 "TxPowerBase and TxPowerEnd included.",
82 MakeUintegerAccessor (&YansWifiPhy::m_nTxPower),
83 MakeUintegerChecker<uint32_t> ())
84 .AddAttribute ("TxPowerEnd",
85 "Maximum available transmission level (dbm).",
86 DoubleValue (16.0206),
87 MakeDoubleAccessor (&YansWifiPhy::SetTxPowerEnd,
88 &YansWifiPhy::GetTxPowerEnd),
89 MakeDoubleChecker<double> ())
90 .AddAttribute ("TxPowerStart",
91 "Minimum available transmission level (dbm).",
92 DoubleValue (16.0206),
93 MakeDoubleAccessor (&YansWifiPhy::SetTxPowerStart,
94 &YansWifiPhy::GetTxPowerStart),
95 MakeDoubleChecker<double> ())
96 .AddAttribute ("RxNoiseFigure",
97 "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver."
98 " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_figure), this is "
99 "\"the difference in decibels (dB) between"
100 " the noise output of the actual receiver to the noise output of an "
101 " ideal receiver with the same overall gain and bandwidth when the receivers "
102 " are connected to sources at the standard noise temperature T0 (usually 290 K)\"."
105 MakeDoubleAccessor (&YansWifiPhy::SetRxNoiseFigure,
106 &YansWifiPhy::GetRxNoiseFigure),
107 MakeDoubleChecker<double> ())
108 .AddAttribute ("State", "The state of the PHY layer",
110 MakePointerAccessor (&YansWifiPhy::m_state),
111 MakePointerChecker<WifiPhyStateHelper> ())
112 .AddAttribute ("ChannelSwitchDelay",
113 "Delay between two short frames transmitted on different frequencies. NOTE: Unused now.",
114 TimeValue (MicroSeconds (250)),
115 MakeTimeAccessor (&YansWifiPhy::m_channelSwitchDelay),
117 .AddAttribute ("ChannelNumber",
118 "Channel center frequency = Channel starting frequency + 5 MHz * (nch - 1)",
120 MakeUintegerAccessor (&YansWifiPhy::SetChannelNumber,
121 &YansWifiPhy::GetChannelNumber),
122 MakeUintegerChecker<uint16_t> ())
128 YansWifiPhy::YansWifiPhy ()
129 : m_channelNumber (1),
132 m_channelStartingFrequency (0)
134 NS_LOG_FUNCTION (this);
135 m_state = CreateObject<WifiPhyStateHelper> ();
138 YansWifiPhy::~YansWifiPhy ()
140 NS_LOG_FUNCTION (this);
144 YansWifiPhy::DoDispose (void)
146 NS_LOG_FUNCTION (this);
155 YansWifiPhy::ConfigureStandard (enum WifiPhyStandard standard)
157 NS_LOG_FUNCTION (this << standard);
159 case WIFI_PHY_STANDARD_80211a:
162 case WIFI_PHY_STANDARD_80211b:
165 case WIFI_PHY_STANDARD_80211_10Mhz:
166 Configure80211_10Mhz ();
168 case WIFI_PHY_STANDARD_80211_5Mhz:
169 Configure80211_5Mhz ();
171 case WIFI_PHY_STANDARD_holland:
182 YansWifiPhy::SetRxNoiseFigure (double noiseFigureDb)
184 NS_LOG_FUNCTION (this << noiseFigureDb);
185 m_interference.SetNoiseFigure (DbToRatio (noiseFigureDb));
188 YansWifiPhy::SetTxPowerStart (double start)
190 NS_LOG_FUNCTION (this << start);
191 m_txPowerBaseDbm = start;
194 YansWifiPhy::SetTxPowerEnd (double end)
196 NS_LOG_FUNCTION (this << end);
197 m_txPowerEndDbm = end;
200 YansWifiPhy::SetNTxPower (uint32_t n)
202 NS_LOG_FUNCTION (this << n);
206 YansWifiPhy::SetTxGain (double gain)
208 NS_LOG_FUNCTION (this << gain);
212 YansWifiPhy::SetRxGain (double gain)
214 NS_LOG_FUNCTION (this << gain);
218 YansWifiPhy::SetEdThreshold (double threshold)
220 NS_LOG_FUNCTION (this << threshold);
221 m_edThresholdW = DbmToW (threshold);
224 YansWifiPhy::SetCcaMode1Threshold (double threshold)
226 NS_LOG_FUNCTION (this << threshold);
227 m_ccaMode1ThresholdW = DbmToW (threshold);
230 YansWifiPhy::SetErrorRateModel (Ptr<ErrorRateModel> rate)
232 m_interference.SetErrorRateModel (rate);
235 YansWifiPhy::SetDevice (Ptr<Object> device)
240 YansWifiPhy::SetMobility (Ptr<Object> mobility)
242 m_mobility = mobility;
246 YansWifiPhy::GetRxNoiseFigure (void) const
248 return RatioToDb (m_interference.GetNoiseFigure ());
251 YansWifiPhy::GetTxPowerStart (void) const
253 return m_txPowerBaseDbm;
256 YansWifiPhy::GetTxPowerEnd (void) const
258 return m_txPowerEndDbm;
261 YansWifiPhy::GetTxGain (void) const
266 YansWifiPhy::GetRxGain (void) const
272 YansWifiPhy::GetEdThreshold (void) const
274 return WToDbm (m_edThresholdW);
278 YansWifiPhy::GetCcaMode1Threshold (void) const
280 return WToDbm (m_ccaMode1ThresholdW);
284 YansWifiPhy::GetErrorRateModel (void) const
286 return m_interference.GetErrorRateModel ();
289 YansWifiPhy::GetDevice (void) const
294 YansWifiPhy::GetMobility (void)
300 YansWifiPhy::CalculateSnr (WifiMode txMode, double ber) const
302 return m_interference.GetErrorRateModel ()->CalculateSnr (txMode, ber);
306 YansWifiPhy::GetChannel (void) const
311 YansWifiPhy::SetChannel (Ptr<YansWifiChannel> channel)
314 m_channel->Add (this);
318 YansWifiPhy::SetChannelNumber (uint16_t nch)
320 NS_ASSERT(!IsStateSwitching());
321 switch (m_state->GetState ()) {
322 case YansWifiPhy::SYNC:
323 NS_LOG_DEBUG ("drop packet because of channel switching while reception");
324 m_endSyncEvent.Cancel();
327 case YansWifiPhy::TX:
328 NS_LOG_DEBUG ("channel switching postponed until end of current transmission");
329 Simulator::Schedule (GetDelayUntilIdle(), &YansWifiPhy::SetChannelNumber, this, nch);
331 case YansWifiPhy::CCA_BUSY:
332 case YansWifiPhy::IDLE:
344 NS_LOG_DEBUG("switching channel " << m_channelNumber << " -> " << nch);
345 m_state->SwitchToChannelSwitching(m_channelSwitchDelay);
346 m_interference.EraseEvents();
348 * Needed here to be able to correctly sensed the medium for the first
349 * time after the switching. The actual switching is not performed until
350 * after m_channelSwitchDelay. Packets received during the switching
351 * state are added to the event list and are employed later to figure
352 * out the state of the medium after the switching.
354 m_channelNumber = nch;
358 YansWifiPhy::GetChannelNumber() const
360 return m_channelNumber;
364 YansWifiPhy::GetChannelFrequencyMhz() const
366 return m_channelStartingFrequency + 5 * (GetChannelNumber() - 1);
370 YansWifiPhy::SetReceiveOkCallback (SyncOkCallback callback)
372 m_state->SetReceiveOkCallback (callback);
375 YansWifiPhy::SetReceiveErrorCallback (SyncErrorCallback callback)
377 m_state->SetReceiveErrorCallback (callback);
380 YansWifiPhy::StartReceivePacket (Ptr<Packet> packet,
383 enum WifiPreamble preamble)
385 NS_LOG_FUNCTION (this << packet << rxPowerDbm << txMode << preamble);
386 rxPowerDbm += m_rxGainDb;
387 double rxPowerW = DbmToW (rxPowerDbm);
388 Time rxDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble);
389 Time endRx = Simulator::Now () + rxDuration;
391 Ptr<InterferenceHelper::Event> event;
392 event = m_interference.Add (packet->GetSize (),
398 switch (m_state->GetState ()) {
399 case YansWifiPhy::SWITCHING:
400 NS_LOG_DEBUG ("drop packet because of channel switching");
401 NotifyRxDrop (packet);
403 * Packets received on the upcoming channel are added to the event list
404 * during the switching state. This way the medium can be correctly sensed
405 * when the device listens to the channel for the first time after the
406 * switching e.g. after channel switching, the channel may be sensed as
407 * busy due to other devices' tramissions started before the end of
410 if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ())
412 // that packet will be noise _after_ the completion of the
413 // channel switching.
417 case YansWifiPhy::SYNC:
418 NS_LOG_DEBUG ("drop packet because already in Sync (power="<<
420 NotifyRxDrop (packet);
421 if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ())
423 // that packet will be noise _after_ the reception of the
424 // currently-received packet.
428 case YansWifiPhy::TX:
429 NS_LOG_DEBUG ("drop packet because already in Tx (power="<<
431 NotifyRxDrop (packet);
432 if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ())
434 // that packet will be noise _after_ the transmission of the
435 // currently-transmitted packet.
439 case YansWifiPhy::CCA_BUSY:
440 case YansWifiPhy::IDLE:
441 if (rxPowerW > m_edThresholdW)
443 NS_LOG_DEBUG ("sync (power="<<rxPowerW<<"W)");
445 m_state->SwitchToSync (rxDuration);
446 NS_ASSERT (m_endSyncEvent.IsExpired ());
447 NotifyRxBegin (packet);
448 m_endSyncEvent = Simulator::Schedule (rxDuration, &YansWifiPhy::EndSync, this,
454 NS_LOG_DEBUG ("drop packet because signal power too Small ("<<
455 rxPowerW<<"<"<<m_edThresholdW<<")");
456 NotifyRxDrop (packet);
465 // We are here because we have received the first bit of a packet and we are
466 // not going to be able to synchronize on it
467 // In this model, CCA becomes busy when the aggregation of all signals as
468 // tracked by the InterferenceHelper class is higher than the CcaBusyThreshold
470 Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaMode1ThresholdW);
471 if (!delayUntilCcaEnd.IsZero ())
473 m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd);
478 YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiMode txMode, WifiPreamble preamble, uint8_t txPower)
480 NS_LOG_FUNCTION (this << packet << txMode << preamble << (uint32_t)txPower);
481 /* Transmission can happen if:
482 * - we are syncing on a packet. It is the responsability of the
483 * MAC layer to avoid doing this but the PHY does nothing to
487 NS_ASSERT (!m_state->IsStateTx () && !m_state->IsStateSwitching ());
489 Time txDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble);
490 if (m_state->IsStateSync ())
492 m_endSyncEvent.Cancel ();
494 NotifyTxBegin (packet);
495 uint32_t dataRate500KbpsUnits = txMode.GetDataRate () / 500000;
496 bool isShortPreamble = (WIFI_PREAMBLE_SHORT == preamble);
497 NotifyPromiscSniffTx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, isShortPreamble);
498 m_state->SwitchToTx (txDuration, packet, txMode, preamble, txPower);
499 m_channel->Send (this, packet, GetPowerDbm (txPower) + m_txGainDb, txMode, preamble);
503 YansWifiPhy::GetNModes (void) const
505 return m_modes.size ();
508 YansWifiPhy::GetMode (uint32_t mode) const
510 return m_modes[mode];
513 YansWifiPhy::GetNTxPower (void) const
519 YansWifiPhy::Configure80211a (void)
521 NS_LOG_FUNCTION (this);
522 m_channelStartingFrequency = 5e3; // 5.000 GHz
523 m_modes.push_back (WifiPhy::Get6mba ());
524 m_modes.push_back (WifiPhy::Get9mba ());
525 m_modes.push_back (WifiPhy::Get12mba ());
526 m_modes.push_back (WifiPhy::Get18mba ());
527 m_modes.push_back (WifiPhy::Get24mba ());
528 m_modes.push_back (WifiPhy::Get36mba ());
529 m_modes.push_back (WifiPhy::Get48mba ());
530 m_modes.push_back (WifiPhy::Get54mba ());
535 YansWifiPhy::Configure80211b (void)
537 NS_LOG_FUNCTION (this);
538 m_channelStartingFrequency = 2412; // 2.412 GHz
539 m_modes.push_back (WifiPhy::Get1mbb ());
540 m_modes.push_back (WifiPhy::Get2mbb ());
541 m_modes.push_back (WifiPhy::Get5_5mbb ());
542 m_modes.push_back (WifiPhy::Get11mbb ());
546 YansWifiPhy::Configure80211_10Mhz (void)
548 NS_LOG_FUNCTION (this);
549 m_channelStartingFrequency = 5e3; // 5.000 GHz, suppose 802.11a
550 m_modes.push_back (WifiPhy::Get3mb10Mhz ());
551 m_modes.push_back (WifiPhy::Get4_5mb10Mhz ());
552 m_modes.push_back (WifiPhy::Get6mb10Mhz ());
553 m_modes.push_back (WifiPhy::Get9mb10Mhz ());
554 m_modes.push_back (WifiPhy::Get12mb10Mhz ());
555 m_modes.push_back (WifiPhy::Get18mb10Mhz ());
556 m_modes.push_back (WifiPhy::Get24mb10Mhz ());
557 m_modes.push_back (WifiPhy::Get27mb10Mhz ());
561 YansWifiPhy::Configure80211_5Mhz (void)
563 NS_LOG_FUNCTION (this);
564 m_channelStartingFrequency = 5e3; // 5.000 GHz, suppose 802.11a
565 m_modes.push_back (WifiPhy::Get1_5mb5Mhz ());
566 m_modes.push_back (WifiPhy::Get2_25mb5Mhz ());
567 m_modes.push_back (WifiPhy::Get3mb5Mhz ());
568 m_modes.push_back (WifiPhy::Get4_5mb5Mhz ());
569 m_modes.push_back (WifiPhy::Get6mb5Mhz ());
570 m_modes.push_back (WifiPhy::Get9mb5Mhz ());
571 m_modes.push_back (WifiPhy::Get12mb5Mhz ());
572 m_modes.push_back (WifiPhy::Get13_5mb5Mhz ());
576 YansWifiPhy::ConfigureHolland (void)
578 NS_LOG_FUNCTION (this);
579 m_channelStartingFrequency = 5e3; // 5.000 GHz
580 m_modes.push_back (WifiPhy::Get6mba ());
581 m_modes.push_back (WifiPhy::Get12mba ());
582 m_modes.push_back (WifiPhy::Get18mba ());
583 m_modes.push_back (WifiPhy::Get36mba ());
584 m_modes.push_back (WifiPhy::Get54mba ());
588 YansWifiPhy::RegisterListener (WifiPhyListener *listener)
590 m_state->RegisterListener (listener);
594 YansWifiPhy::IsStateCcaBusy (void)
596 return m_state->IsStateCcaBusy ();
600 YansWifiPhy::IsStateIdle (void)
602 return m_state->IsStateIdle ();
605 YansWifiPhy::IsStateBusy (void)
607 return m_state->IsStateBusy ();
610 YansWifiPhy::IsStateSync (void)
612 return m_state->IsStateSync ();
615 YansWifiPhy::IsStateTx (void)
617 return m_state->IsStateTx ();
620 YansWifiPhy::IsStateSwitching (void)
622 return m_state->IsStateSwitching ();
626 YansWifiPhy::GetStateDuration (void)
628 return m_state->GetStateDuration ();
631 YansWifiPhy::GetDelayUntilIdle (void)
633 return m_state->GetDelayUntilIdle ();
637 YansWifiPhy::GetLastRxStartTime (void) const
639 return m_state->GetLastRxStartTime ();
643 YansWifiPhy::CalculateTxDuration (uint32_t size, WifiMode payloadMode, enum WifiPreamble preamble) const
645 return m_interference.CalculateTxDuration (size, payloadMode, preamble);
649 YansWifiPhy::DbToRatio (double dB) const
651 double ratio = pow(10.0,dB/10.0);
656 YansWifiPhy::DbmToW (double dBm) const
658 double mW = pow(10.0,dBm/10.0);
663 YansWifiPhy::WToDbm (double w) const
665 return 10.0 * log10(w * 1000.0);
669 YansWifiPhy::RatioToDb (double ratio) const
671 return 10.0 * log10(ratio);
675 YansWifiPhy::GetEdThresholdW (void) const
677 return m_edThresholdW;
681 YansWifiPhy::GetPowerDbm (uint8_t power) const
683 NS_ASSERT (m_txPowerBaseDbm <= m_txPowerEndDbm);
684 NS_ASSERT (m_nTxPower > 0);
685 double dbm = m_txPowerBaseDbm + power * (m_txPowerEndDbm - m_txPowerBaseDbm) / m_nTxPower;
690 YansWifiPhy::EndSync (Ptr<Packet> packet, Ptr<InterferenceHelper::Event> event)
692 NS_LOG_FUNCTION (this << packet << event);
693 NS_ASSERT (IsStateSync ());
694 NS_ASSERT (event->GetEndTime () == Simulator::Now ());
696 struct InterferenceHelper::SnrPer snrPer;
697 snrPer = m_interference.CalculateSnrPer (event);
699 NS_LOG_DEBUG ("mode="<<(event->GetPayloadMode ().GetDataRate ())<<
700 ", snr="<<snrPer.snr<<", per="<<snrPer.per<<", size="<<packet->GetSize ());
701 if (m_random.GetValue () > snrPer.per)
703 NotifyRxEnd (packet);
704 uint32_t dataRate500KbpsUnits = event->GetPayloadMode ().GetDataRate () / 500000;
705 bool isShortPreamble = (WIFI_PREAMBLE_SHORT == event->GetPreambleType ());
706 double signalDbm = RatioToDb (event->GetRxPowerW ()) + 30;
707 double noiseDbm = RatioToDb(event->GetRxPowerW() / snrPer.snr) - GetRxNoiseFigure() + 30 ;
708 NotifyPromiscSniffRx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, isShortPreamble, signalDbm, noiseDbm);
709 m_state->SwitchFromSyncEndOk (packet, snrPer.snr, event->GetPayloadMode (), event->GetPreambleType ());
714 NotifyRxDrop (packet);
715 m_state->SwitchFromSyncEndError (packet, snrPer.snr);