diff options
Diffstat (limited to 'emu-radio/ns3-patch/wifi/model/yans-wifi-phy.cc')
-rw-r--r-- | emu-radio/ns3-patch/wifi/model/yans-wifi-phy.cc | 1390 |
1 files changed, 1390 insertions, 0 deletions
diff --git a/emu-radio/ns3-patch/wifi/model/yans-wifi-phy.cc b/emu-radio/ns3-patch/wifi/model/yans-wifi-phy.cc new file mode 100644 index 00000000..dfc5323c --- /dev/null +++ b/emu-radio/ns3-patch/wifi/model/yans-wifi-phy.cc @@ -0,0 +1,1390 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> + * Ghada Badawy <gbadawy@gmail.com> + * Sébastien Deronne <sebastien.deronne@gmail.com> + */ + +#include "yans-wifi-phy.h" +#include "yans-wifi-channel.h" +#include "wifi-mode.h" +#include "wifi-preamble.h" +#include "wifi-phy-state-helper.h" +#include "error-rate-model.h" +#include "ns3/simulator.h" +#include "ns3/packet.h" +#include "ns3/assert.h" +#include "ns3/log.h" +#include "ns3/double.h" +#include "ns3/uinteger.h" +#include "ns3/enum.h" +#include "ns3/pointer.h" +#include "ns3/net-device.h" +#include "ns3/trace-source-accessor.h" +#include "ns3/boolean.h" +#include "ns3/node.h" +#include "ampdu-tag.h" +#include <cmath> + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("YansWifiPhy"); + +NS_OBJECT_ENSURE_REGISTERED (YansWifiPhy); + +TypeId +RssiTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::RssiTag") + .SetParent<SnrTag> () + .SetGroupName ("Wifi") + .AddConstructor<RssiTag> () + .AddAttribute ("RSSI", "The RSSI of the last packet received", + DoubleValue (0.0), + MakeDoubleAccessor (&RssiTag::Get), + MakeDoubleChecker<double> ()) + ; + return tid; +} + +TypeId +RssiTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +RssiTag::RssiTag() +:SnrTag() +{} + +RssiTag::RssiTag (double snr) +:SnrTag(snr) +{} + +TypeId +YansWifiPhy::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::YansWifiPhy") + .SetParent<WifiPhy> () + .SetGroupName ("Wifi") + .AddConstructor<YansWifiPhy> () + .AddAttribute ("EnergyDetectionThreshold", + "The energy of a received signal should be higher than " + "this threshold (dbm) to allow the PHY layer to detect the signal.", + DoubleValue (-96.0), + MakeDoubleAccessor (&YansWifiPhy::SetEdThreshold, + &YansWifiPhy::GetEdThreshold), + MakeDoubleChecker<double> ()) + .AddAttribute ("CcaMode1Threshold", + "The energy of a received signal should be higher than " + "this threshold (dbm) to allow the PHY layer to declare CCA BUSY state.", + DoubleValue (-99.0), + MakeDoubleAccessor (&YansWifiPhy::SetCcaMode1Threshold, + &YansWifiPhy::GetCcaMode1Threshold), + MakeDoubleChecker<double> ()) + .AddAttribute ("TxGain", + "Transmission gain (dB).", + DoubleValue (1.0), + MakeDoubleAccessor (&YansWifiPhy::SetTxGain, + &YansWifiPhy::GetTxGain), + MakeDoubleChecker<double> ()) + .AddAttribute ("RxGain", + "Reception gain (dB).", + DoubleValue (1.0), + MakeDoubleAccessor (&YansWifiPhy::SetRxGain, + &YansWifiPhy::GetRxGain), + MakeDoubleChecker<double> ()) + .AddAttribute ("TxPowerLevels", + "Number of transmission power levels available between " + "TxPowerStart and TxPowerEnd included.", + UintegerValue (1), + MakeUintegerAccessor (&YansWifiPhy::m_nTxPower), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("TxPowerEnd", + "Maximum available transmission level (dbm).", + DoubleValue (16.0206), + MakeDoubleAccessor (&YansWifiPhy::SetTxPowerEnd, + &YansWifiPhy::GetTxPowerEnd), + MakeDoubleChecker<double> ()) + .AddAttribute ("TxPowerStart", + "Minimum available transmission level (dbm).", + DoubleValue (16.0206), + MakeDoubleAccessor (&YansWifiPhy::SetTxPowerStart, + &YansWifiPhy::GetTxPowerStart), + MakeDoubleChecker<double> ()) + .AddAttribute ("RxNoiseFigure", + "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver." + " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_figure), this is " + "\"the difference in decibels (dB) between" + " the noise output of the actual receiver to the noise output of an " + " ideal receiver with the same overall gain and bandwidth when the receivers " + " are connected to sources at the standard noise temperature T0 (usually 290 K)\".", + DoubleValue (7), + MakeDoubleAccessor (&YansWifiPhy::SetRxNoiseFigure, + &YansWifiPhy::GetRxNoiseFigure), + MakeDoubleChecker<double> ()) + .AddAttribute ("State", + "The state of the PHY layer.", + PointerValue (), + MakePointerAccessor (&YansWifiPhy::m_state), + MakePointerChecker<WifiPhyStateHelper> ()) + .AddAttribute ("ChannelSwitchDelay", + "Delay between two short frames transmitted on different frequencies.", + TimeValue (MicroSeconds (250)), + MakeTimeAccessor (&YansWifiPhy::m_channelSwitchDelay), + MakeTimeChecker ()) + .AddAttribute ("ChannelNumber", + "Channel center frequency = Channel starting frequency + 5 MHz * nch.", + UintegerValue (1), + MakeUintegerAccessor (&YansWifiPhy::SetChannelNumber, + &YansWifiPhy::GetChannelNumber), + MakeUintegerChecker<uint16_t> ()) + .AddAttribute ("Frequency", + "The operating frequency.", + UintegerValue (2407), + MakeUintegerAccessor (&YansWifiPhy::GetFrequency, + &YansWifiPhy::SetFrequency), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("Transmitters", + "The number of transmitters.", + UintegerValue (1), + MakeUintegerAccessor (&YansWifiPhy::GetNumberOfTransmitAntennas, + &YansWifiPhy::SetNumberOfTransmitAntennas), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("Receivers", + "The number of receivers.", + UintegerValue (1), + MakeUintegerAccessor (&YansWifiPhy::GetNumberOfReceiveAntennas, + &YansWifiPhy::SetNumberOfReceiveAntennas), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("ShortGuardEnabled", + "Whether or not short guard interval is enabled.", + BooleanValue (false), + MakeBooleanAccessor (&YansWifiPhy::GetGuardInterval, + &YansWifiPhy::SetGuardInterval), + MakeBooleanChecker ()) + .AddAttribute ("LdpcEnabled", + "Whether or not LDPC is enabled.", + BooleanValue (false), + MakeBooleanAccessor (&YansWifiPhy::GetLdpc, + &YansWifiPhy::SetLdpc), + MakeBooleanChecker ()) + .AddAttribute ("STBCEnabled", + "Whether or not STBC is enabled.", + BooleanValue (false), + MakeBooleanAccessor (&YansWifiPhy::GetStbc, + &YansWifiPhy::SetStbc), + MakeBooleanChecker ()) + .AddAttribute ("GreenfieldEnabled", + "Whether or not Greenfield is enabled.", + BooleanValue (false), + MakeBooleanAccessor (&YansWifiPhy::GetGreenfield, + &YansWifiPhy::SetGreenfield), + MakeBooleanChecker ()) + .AddAttribute ("ChannelWidth", + "Whether 5MHz, 10MHz, 20MHz, 22MHz, 40MHz, 80 MHz or 160 MHz.", + UintegerValue (20), + MakeUintegerAccessor (&YansWifiPhy::GetChannelWidth, + &YansWifiPhy::SetChannelWidth), + MakeUintegerChecker<uint32_t> ()) + ; + return tid; +} + +YansWifiPhy::YansWifiPhy () + : m_initialized (false), + m_channelNumber (1), + m_endRxEvent (), + m_endPlcpRxEvent (), + m_channelStartingFrequency (0), + m_mpdusNum (0), + m_plcpSuccess (false) +{ + NS_LOG_FUNCTION (this); + m_random = CreateObject<UniformRandomVariable> (); + m_state = CreateObject<WifiPhyStateHelper> (); +} + +YansWifiPhy::~YansWifiPhy () +{ + NS_LOG_FUNCTION (this); +} + +void +YansWifiPhy::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + m_channel = 0; + m_deviceRateSet.clear (); + m_deviceMcsSet.clear (); + m_device = 0; + m_mobility = 0; + m_state = 0; +} + +void +YansWifiPhy::DoInitialize () +{ + NS_LOG_FUNCTION (this); + m_initialized = true; +} + +void +YansWifiPhy::ConfigureStandard (enum WifiPhyStandard standard) +{ + NS_LOG_FUNCTION (this << standard); + switch (standard) + { + case WIFI_PHY_STANDARD_80211a: + Configure80211a (); + break; + case WIFI_PHY_STANDARD_80211b: + Configure80211b (); + break; + case WIFI_PHY_STANDARD_80211g: + Configure80211g (); + break; + case WIFI_PHY_STANDARD_80211_10MHZ: + Configure80211_10Mhz (); + break; + case WIFI_PHY_STANDARD_80211_5MHZ: + Configure80211_5Mhz (); + break; + case WIFI_PHY_STANDARD_holland: + ConfigureHolland (); + break; + case WIFI_PHY_STANDARD_80211n_2_4GHZ: + m_channelStartingFrequency = 2407; + Configure80211n (); + break; + case WIFI_PHY_STANDARD_80211n_5GHZ: + m_channelStartingFrequency = 5e3; + Configure80211n (); + break; + case WIFI_PHY_STANDARD_80211ac: + Configure80211ac (); + break; + default: + NS_ASSERT (false); + break; + } +} + +void +YansWifiPhy::SetRxNoiseFigure (double noiseFigureDb) +{ + NS_LOG_FUNCTION (this << noiseFigureDb); + m_interference.SetNoiseFigure (DbToRatio (noiseFigureDb)); +} + +void +YansWifiPhy::SetTxPowerStart (double start) +{ + NS_LOG_FUNCTION (this << start); + m_txPowerBaseDbm = start; +} + +void +YansWifiPhy::SetTxPowerEnd (double end) +{ + NS_LOG_FUNCTION (this << end); + m_txPowerEndDbm = end; +} + +void +YansWifiPhy::SetNTxPower (uint32_t n) +{ + NS_LOG_FUNCTION (this << n); + m_nTxPower = n; +} + +void +YansWifiPhy::SetTxGain (double gain) +{ + NS_LOG_FUNCTION (this << gain); + m_txGainDb = gain; +} + +void +YansWifiPhy::SetRxGain (double gain) +{ + NS_LOG_FUNCTION (this << gain); + m_rxGainDb = gain; +} + +void +YansWifiPhy::SetEdThreshold (double threshold) +{ + NS_LOG_FUNCTION (this << threshold); + m_edThresholdW = DbmToW (threshold); +} + +void +YansWifiPhy::SetCcaMode1Threshold (double threshold) +{ + NS_LOG_FUNCTION (this << threshold); + m_ccaMode1ThresholdW = DbmToW (threshold); +} + +void +YansWifiPhy::SetErrorRateModel (Ptr<ErrorRateModel> rate) +{ + m_interference.SetErrorRateModel (rate); +} + +void +YansWifiPhy::SetDevice (Ptr<NetDevice> device) +{ + m_device = device; +} + +void +YansWifiPhy::SetMobility (Ptr<MobilityModel> mobility) +{ + m_mobility = mobility; +} + +double +YansWifiPhy::GetRxNoiseFigure (void) const +{ + return RatioToDb (m_interference.GetNoiseFigure ()); +} + +double +YansWifiPhy::GetTxPowerStart (void) const +{ + return m_txPowerBaseDbm; +} + +double +YansWifiPhy::GetTxPowerEnd (void) const +{ + return m_txPowerEndDbm; +} + +double +YansWifiPhy::GetTxGain (void) const +{ + return m_txGainDb; +} + +double +YansWifiPhy::GetRxGain (void) const +{ + return m_rxGainDb; +} + +double +YansWifiPhy::GetEdThreshold (void) const +{ + return WToDbm (m_edThresholdW); +} + +double +YansWifiPhy::GetCcaMode1Threshold (void) const +{ + return WToDbm (m_ccaMode1ThresholdW); +} + +Ptr<ErrorRateModel> +YansWifiPhy::GetErrorRateModel (void) const +{ + return m_interference.GetErrorRateModel (); +} + +Ptr<NetDevice> +YansWifiPhy::GetDevice (void) const +{ + return m_device; +} + +Ptr<MobilityModel> +YansWifiPhy::GetMobility (void) +{ + if (m_mobility != 0) + { + return m_mobility; + } + else + { + return m_device->GetNode ()->GetObject<MobilityModel> (); + } +} + +double +YansWifiPhy::CalculateSnr (WifiMode txMode, double ber) const +{ + return m_interference.GetErrorRateModel ()->CalculateSnr (txMode, ber); +} + +Ptr<WifiChannel> +YansWifiPhy::GetChannel (void) const +{ + return m_channel; +} + +void +YansWifiPhy::SetChannel (Ptr<YansWifiChannel> channel) +{ + m_channel = channel; + m_channel->Add (this); +} + +void +YansWifiPhy::SetChannelNumber (uint16_t nch) +{ + if (!m_initialized) + { + //this is not channel switch, this is initialization + NS_LOG_DEBUG ("start at channel " << nch); + m_channelNumber = nch; + return; + } + + NS_ASSERT (!IsStateSwitching ()); + switch (m_state->GetState ()) + { + case YansWifiPhy::RX: + NS_LOG_DEBUG ("drop packet because of channel switching while reception"); + m_endPlcpRxEvent.Cancel (); + m_endRxEvent.Cancel (); + goto switchChannel; + break; + case YansWifiPhy::TX: + NS_LOG_DEBUG ("channel switching postponed until end of current transmission"); + Simulator::Schedule (GetDelayUntilIdle (), &YansWifiPhy::SetChannelNumber, this, nch); + break; + case YansWifiPhy::CCA_BUSY: + case YansWifiPhy::IDLE: + goto switchChannel; + break; + case YansWifiPhy::SLEEP: + NS_LOG_DEBUG ("channel switching ignored in sleep mode"); + break; + default: + NS_ASSERT (false); + break; + } + + return; + +switchChannel: + + NS_LOG_DEBUG ("switching channel " << m_channelNumber << " -> " << nch); + m_state->SwitchToChannelSwitching (m_channelSwitchDelay); + m_interference.EraseEvents (); + /* + * Needed here to be able to correctly sensed the medium for the first + * time after the switching. The actual switching is not performed until + * after m_channelSwitchDelay. Packets received during the switching + * state are added to the event list and are employed later to figure + * out the state of the medium after the switching. + */ + m_channelNumber = nch; +} + +uint16_t +YansWifiPhy::GetChannelNumber (void) const +{ + return m_channelNumber; +} + +Time +YansWifiPhy::GetChannelSwitchDelay (void) const +{ + return m_channelSwitchDelay; +} + +double +YansWifiPhy::GetChannelFrequencyMhz () const +{ + return m_channelStartingFrequency + 5 * GetChannelNumber (); +} + +void +YansWifiPhy::SetSleepMode (void) +{ + NS_LOG_FUNCTION (this); + switch (m_state->GetState ()) + { + case YansWifiPhy::TX: + NS_LOG_DEBUG ("setting sleep mode postponed until end of current transmission"); + Simulator::Schedule (GetDelayUntilIdle (), &YansWifiPhy::SetSleepMode, this); + break; + case YansWifiPhy::RX: + NS_LOG_DEBUG ("setting sleep mode postponed until end of current reception"); + Simulator::Schedule (GetDelayUntilIdle (), &YansWifiPhy::SetSleepMode, this); + break; + case YansWifiPhy::SWITCHING: + NS_LOG_DEBUG ("setting sleep mode postponed until end of channel switching"); + Simulator::Schedule (GetDelayUntilIdle (), &YansWifiPhy::SetSleepMode, this); + break; + case YansWifiPhy::CCA_BUSY: + case YansWifiPhy::IDLE: + NS_LOG_DEBUG ("setting sleep mode"); + m_state->SwitchToSleep (); + break; + case YansWifiPhy::SLEEP: + NS_LOG_DEBUG ("already in sleep mode"); + break; + default: + NS_ASSERT (false); + break; + } +} + +void +YansWifiPhy::ResumeFromSleep (void) +{ + NS_LOG_FUNCTION (this); + switch (m_state->GetState ()) + { + case YansWifiPhy::TX: + case YansWifiPhy::RX: + case YansWifiPhy::IDLE: + case YansWifiPhy::CCA_BUSY: + case YansWifiPhy::SWITCHING: + { + NS_LOG_DEBUG ("not in sleep mode, there is nothing to resume"); + break; + } + case YansWifiPhy::SLEEP: + { + NS_LOG_DEBUG ("resuming from sleep mode"); + Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaMode1ThresholdW); + m_state->SwitchFromSleep (delayUntilCcaEnd); + break; + } + default: + { + NS_ASSERT (false); + break; + } + } +} + +void +YansWifiPhy::SetReceiveOkCallback (RxOkCallback callback) +{ + m_state->SetReceiveOkCallback (callback); +} + +void +YansWifiPhy::SetReceiveErrorCallback (RxErrorCallback callback) +{ + m_state->SetReceiveErrorCallback (callback); +} + +void +YansWifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, + double rxPowerDbm, + WifiTxVector txVector, + enum WifiPreamble preamble, + struct mpduInfo aMpdu, Time rxDuration) +{ + //This function should be later split to check separately whether plcp preamble and plcp header can be successfully received. + //Note: plcp preamble reception is not yet modeled. + NS_LOG_FUNCTION (this << packet << rxPowerDbm << txVector.GetMode () << preamble << (uint32_t)aMpdu.packetType); + AmpduTag ampduTag; + rxPowerDbm += m_rxGainDb; + double rxPowerW = DbmToW (rxPowerDbm); + Time endRx = Simulator::Now () + rxDuration; + Time preambleAndHeaderDuration = CalculatePlcpPreambleAndHeaderDuration (txVector, preamble); + + Ptr<InterferenceHelper::Event> event; + event = m_interference.Add (packet->GetSize (), + txVector, + preamble, + rxDuration, + rxPowerW); + + switch (m_state->GetState ()) + { + case YansWifiPhy::SWITCHING: + NS_LOG_DEBUG ("drop packet because of channel switching"); + NotifyRxDrop (packet); + m_plcpSuccess = false; + /* + * Packets received on the upcoming channel are added to the event list + * during the switching state. This way the medium can be correctly sensed + * when the device listens to the channel for the first time after the + * switching e.g. after channel switching, the channel may be sensed as + * busy due to other devices' tramissions started before the end of + * the switching. + */ + if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ()) + { + //that packet will be noise _after_ the completion of the + //channel switching. + goto maybeCcaBusy; + } + break; + case YansWifiPhy::RX: + NS_LOG_DEBUG ("drop packet because already in Rx (power=" << + rxPowerW << "W)"); + NotifyRxDrop (packet); + if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ()) + { + //that packet will be noise _after_ the reception of the + //currently-received packet. + goto maybeCcaBusy; + } + break; + case YansWifiPhy::TX: + NS_LOG_DEBUG ("drop packet because already in Tx (power=" << + rxPowerW << "W)"); + NotifyRxDrop (packet); + if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ()) + { + //that packet will be noise _after_ the transmission of the + //currently-transmitted packet. + goto maybeCcaBusy; + } + break; + case YansWifiPhy::CCA_BUSY: + case YansWifiPhy::IDLE: + if (rxPowerW > m_edThresholdW) //checked here, no need to check in the payload reception (current implementation assumes constant rx power over the packet duration) + { + if (preamble == WIFI_PREAMBLE_NONE && m_mpdusNum == 0) + { + NS_LOG_DEBUG ("drop packet because no preamble has been received"); + NotifyRxDrop (packet); + goto maybeCcaBusy; + } + else if (preamble == WIFI_PREAMBLE_NONE && m_plcpSuccess == false) //A-MPDU reception fails + { + NS_LOG_DEBUG ("Drop MPDU because no plcp has been received"); + NotifyRxDrop (packet); + goto maybeCcaBusy; + } + else if (preamble != WIFI_PREAMBLE_NONE && packet->PeekPacketTag (ampduTag) && m_mpdusNum == 0) + { + //received the first MPDU in an MPDU + m_mpdusNum = ampduTag.GetNoOfMpdus () - 1; + } + else if (preamble == WIFI_PREAMBLE_NONE && packet->PeekPacketTag (ampduTag) && m_mpdusNum > 0) + { + //received the other MPDUs that are part of the A-MPDU + if (ampduTag.GetNoOfMpdus () < m_mpdusNum) + { + NS_LOG_DEBUG ("Missing MPDU from the A-MPDU " << m_mpdusNum - ampduTag.GetNoOfMpdus ()); + m_mpdusNum = ampduTag.GetNoOfMpdus (); + } + else + { + m_mpdusNum--; + } + } + else if (preamble != WIFI_PREAMBLE_NONE && m_mpdusNum > 0 ) + { + NS_LOG_DEBUG ("Didn't receive the last MPDUs from an A-MPDU " << m_mpdusNum); + m_mpdusNum = 0; + } + + NS_LOG_DEBUG ("sync to signal (power=" << rxPowerW << "W)"); + //sync to signal + m_state->SwitchToRx (rxDuration); + NS_ASSERT (m_endPlcpRxEvent.IsExpired ()); + NotifyRxBegin (packet); + m_interference.NotifyRxStart (); + + if (preamble != WIFI_PREAMBLE_NONE) + { + NS_ASSERT (m_endPlcpRxEvent.IsExpired ()); + m_endPlcpRxEvent = Simulator::Schedule (preambleAndHeaderDuration, &YansWifiPhy::StartReceivePacket, this, + packet, txVector, preamble, aMpdu, event); + } + + NS_ASSERT (m_endRxEvent.IsExpired ()); + m_endRxEvent = Simulator::Schedule (rxDuration, &YansWifiPhy::EndReceive, this, + packet, preamble, aMpdu, event); + } + else + { + NS_LOG_DEBUG ("drop packet because signal power too Small (" << + rxPowerW << "<" << m_edThresholdW << ")"); + NotifyRxDrop (packet); + m_plcpSuccess = false; + goto maybeCcaBusy; + } + break; + case YansWifiPhy::SLEEP: + NS_LOG_DEBUG ("drop packet because in sleep mode"); + NotifyRxDrop (packet); + m_plcpSuccess = false; + break; + } + + return; + +maybeCcaBusy: + //We are here because we have received the first bit of a packet and we are + //not going to be able to synchronize on it + //In this model, CCA becomes busy when the aggregation of all signals as + //tracked by the InterferenceHelper class is higher than the CcaBusyThreshold + + Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaMode1ThresholdW); + if (!delayUntilCcaEnd.IsZero ()) + { + m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd); + } +} + +void +YansWifiPhy::StartReceivePacket (Ptr<Packet> packet, + WifiTxVector txVector, + enum WifiPreamble preamble, + struct mpduInfo aMpdu, + Ptr<InterferenceHelper::Event> event) +{ + NS_LOG_FUNCTION (this << packet << txVector.GetMode () << preamble << (uint32_t)aMpdu.packetType); + NS_ASSERT (IsStateRx ()); + NS_ASSERT (m_endPlcpRxEvent.IsExpired ()); + AmpduTag ampduTag; + WifiMode txMode = txVector.GetMode (); + + struct InterferenceHelper::SnrPer snrPer; + snrPer = m_interference.CalculatePlcpHeaderSnrPer (event); + + NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per); + + if (m_random->GetValue () > snrPer.per) //plcp reception succeeded + { + if (IsModeSupported (txMode) || IsMcsSupported (txMode)) + { + NS_LOG_DEBUG ("receiving plcp payload"); //endReceive is already scheduled + m_plcpSuccess = true; + } + else //mode is not allowed + { + NS_LOG_DEBUG ("drop packet because it was sent using an unsupported mode (" << txMode << ")"); + NotifyRxDrop (packet); + m_plcpSuccess = false; + } + } + else //plcp reception failed + { + NS_LOG_DEBUG ("drop packet because plcp preamble/header reception failed"); + NotifyRxDrop (packet); + m_plcpSuccess = false; + } +} + +void +YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, uint32_t mpduReferenceNumber) +{ + NS_LOG_FUNCTION (this << packet << txVector.GetMode () << txVector.GetMode ().GetDataRate (txVector.GetChannelWidth (), txVector.IsShortGuardInterval (), 1) << preamble << (uint32_t)txVector.GetTxPowerLevel () << (uint32_t)packetType); + /* Transmission can happen if: + * - we are syncing on a packet. It is the responsability of the + * MAC layer to avoid doing this but the PHY does nothing to + * prevent it. + * - we are idle + */ + NS_ASSERT (!m_state->IsStateTx () && !m_state->IsStateSwitching ()); + + if (m_state->IsStateSleep ()) + { + NS_LOG_DEBUG ("Dropping packet because in sleep mode"); + NotifyTxDrop (packet); + return; + } + + Time txDuration = CalculateTxDuration (packet->GetSize (), txVector, preamble, GetFrequency (), packetType, 1); + NS_ASSERT (txDuration > NanoSeconds (0)); + + if (m_state->IsStateRx ()) + { + m_endPlcpRxEvent.Cancel (); + m_endRxEvent.Cancel (); + m_interference.NotifyRxEnd (); + } + NotifyTxBegin (packet); + uint32_t dataRate500KbpsUnits; + if (txVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT || txVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_VHT) + { + dataRate500KbpsUnits = 128 + txVector.GetMode ().GetMcsValue (); + } + else + { + dataRate500KbpsUnits = txVector.GetMode ().GetDataRate (txVector.GetChannelWidth (), txVector.IsShortGuardInterval (), 1) * txVector.GetNss () / 500000; + } + struct mpduInfo aMpdu; + aMpdu.packetType = packetType; + aMpdu.referenceNumber = mpduReferenceNumber; + NotifyMonitorSniffTx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, preamble, txVector, aMpdu); + m_state->SwitchToTx (txDuration, packet, GetPowerDbm (txVector.GetTxPowerLevel ()), txVector, preamble); + m_channel->Send (this, packet, GetPowerDbm (txVector.GetTxPowerLevel ()) + m_txGainDb, txVector, preamble, aMpdu, txDuration); +} + +uint32_t +YansWifiPhy::GetNModes (void) const +{ + return m_deviceRateSet.size (); +} + +WifiMode +YansWifiPhy::GetMode (uint32_t mode) const +{ + return m_deviceRateSet[mode]; +} + +bool +YansWifiPhy::IsModeSupported (WifiMode mode) const +{ + for (uint32_t i = 0; i < GetNModes (); i++) + { + if (mode == GetMode (i)) + { + return true; + } + } + return false; +} +bool +YansWifiPhy::IsMcsSupported (WifiMode mcs) +{ + for (uint32_t i = 0; i < GetNMcs (); i++) + { + if (mcs == GetMcs (i)) + { + return true; + } + } + return false; +} + +uint32_t +YansWifiPhy::GetNTxPower (void) const +{ + return m_nTxPower; +} + +void +YansWifiPhy::Configure80211a (void) +{ + NS_LOG_FUNCTION (this); + m_channelStartingFrequency = 5e3; //5.000 GHz + SetChannelWidth (20); //20 MHz + + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate9Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate18Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate24Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate36Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate48Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate54Mbps ()); +} + +void +YansWifiPhy::Configure80211b (void) +{ + NS_LOG_FUNCTION (this); + m_channelStartingFrequency = 2407; //2.407 GHz + SetChannelWidth (22); //22 MHz + + m_deviceRateSet.push_back (WifiPhy::GetDsssRate1Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetDsssRate2Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetDsssRate5_5Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetDsssRate11Mbps ()); +} + +void +YansWifiPhy::Configure80211g (void) +{ + NS_LOG_FUNCTION (this); + m_channelStartingFrequency = 2407; //2.407 GHz + SetChannelWidth (20); //20 MHz + + m_deviceRateSet.push_back (WifiPhy::GetDsssRate1Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetDsssRate2Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetDsssRate5_5Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate6Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate9Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetDsssRate11Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate12Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate18Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate24Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate36Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate48Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate54Mbps ()); +} + +void +YansWifiPhy::Configure80211_10Mhz (void) +{ + NS_LOG_FUNCTION (this); + m_channelStartingFrequency = 5e3; //5.000 GHz, suppose 802.11a + SetChannelWidth (10); //10 MHz + + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate3MbpsBW10MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate4_5MbpsBW10MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6MbpsBW10MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate9MbpsBW10MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12MbpsBW10MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate18MbpsBW10MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate24MbpsBW10MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate27MbpsBW10MHz ()); +} + +void +YansWifiPhy::Configure80211_5Mhz (void) +{ + NS_LOG_FUNCTION (this); + m_channelStartingFrequency = 5e3; //5.000 GHz, suppose 802.11a + SetChannelWidth (5); //5 MHz + + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate1_5MbpsBW5MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate2_25MbpsBW5MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate3MbpsBW5MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate4_5MbpsBW5MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6MbpsBW5MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate9MbpsBW5MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12MbpsBW5MHz ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate13_5MbpsBW5MHz ()); +} + +void +YansWifiPhy::ConfigureHolland (void) +{ + NS_LOG_FUNCTION (this); + m_channelStartingFrequency = 5e3; //5.000 GHz + SetChannelWidth (20); //20 MHz + + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate18Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate36Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate54Mbps ()); +} + +void +YansWifiPhy::Configure80211n (void) +{ + NS_LOG_FUNCTION (this); + SetChannelWidth (20); //20 MHz + if (m_channelStartingFrequency >= 2400 && m_channelStartingFrequency <= 2500) //at 2.4 GHz + { + m_deviceRateSet.push_back (WifiPhy::GetDsssRate1Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetDsssRate2Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetDsssRate5_5Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate6Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetDsssRate11Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate12Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate24Mbps ()); + } + if (m_channelStartingFrequency >= 5000 && m_channelStartingFrequency <= 6000) //at 5 GHz + { + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate24Mbps ()); + } + + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs0 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs1 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs2 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs3 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs4 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs5 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs6 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs7 ()); + + m_bssMembershipSelectorSet.push_back (HT_PHY); +} + +void +YansWifiPhy::Configure80211ac (void) +{ + NS_LOG_FUNCTION (this); + m_channelStartingFrequency = 5e3; //5.000 GHz + SetChannelWidth (80); //80 MHz + + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12Mbps ()); + m_deviceRateSet.push_back (WifiPhy::GetOfdmRate24Mbps ()); + + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs0 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs1 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs2 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs3 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs4 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs5 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs6 ()); + m_deviceMcsSet.push_back (WifiPhy::GetHtMcs7 ()); + + m_deviceMcsSet.push_back (WifiPhy::GetVhtMcs0 ()); + m_deviceMcsSet.push_back (WifiPhy::GetVhtMcs1 ()); + m_deviceMcsSet.push_back (WifiPhy::GetVhtMcs2 ()); + m_deviceMcsSet.push_back (WifiPhy::GetVhtMcs3 ()); + m_deviceMcsSet.push_back (WifiPhy::GetVhtMcs4 ()); + m_deviceMcsSet.push_back (WifiPhy::GetVhtMcs5 ()); + m_deviceMcsSet.push_back (WifiPhy::GetVhtMcs6 ()); + m_deviceMcsSet.push_back (WifiPhy::GetVhtMcs7 ()); + m_deviceMcsSet.push_back (WifiPhy::GetVhtMcs8 ()); + m_deviceMcsSet.push_back (WifiPhy::GetVhtMcs9 ()); + + m_bssMembershipSelectorSet.push_back (VHT_PHY); +} + +void +YansWifiPhy::RegisterListener (WifiPhyListener *listener) +{ + m_state->RegisterListener (listener); +} + +void +YansWifiPhy::UnregisterListener (WifiPhyListener *listener) +{ + m_state->UnregisterListener (listener); +} + +bool +YansWifiPhy::IsStateCcaBusy (void) +{ + return m_state->IsStateCcaBusy (); +} + +bool +YansWifiPhy::IsStateIdle (void) +{ + return m_state->IsStateIdle (); +} + +bool +YansWifiPhy::IsStateBusy (void) +{ + return m_state->IsStateBusy (); +} + +bool +YansWifiPhy::IsStateRx (void) +{ + return m_state->IsStateRx (); +} + +bool +YansWifiPhy::IsStateTx (void) +{ + return m_state->IsStateTx (); +} + +bool +YansWifiPhy::IsStateSwitching (void) +{ + return m_state->IsStateSwitching (); +} + +bool +YansWifiPhy::IsStateSleep (void) +{ + return m_state->IsStateSleep (); +} + +Time +YansWifiPhy::GetStateDuration (void) +{ + return m_state->GetStateDuration (); +} + +Time +YansWifiPhy::GetDelayUntilIdle (void) +{ + return m_state->GetDelayUntilIdle (); +} + +Time +YansWifiPhy::GetLastRxStartTime (void) const +{ + return m_state->GetLastRxStartTime (); +} + +double +YansWifiPhy::DbToRatio (double dB) const +{ + double ratio = std::pow (10.0, dB / 10.0); + return ratio; +} + +double +YansWifiPhy::DbmToW (double dBm) const +{ + double mW = std::pow (10.0, dBm / 10.0); + return mW / 1000.0; +} + +double +YansWifiPhy::WToDbm (double w) const +{ + return 10.0 * std::log10 (w * 1000.0); +} + +double +YansWifiPhy::RatioToDb (double ratio) const +{ + return 10.0 * std::log10 (ratio); +} + +double +YansWifiPhy::GetEdThresholdW (void) const +{ + return m_edThresholdW; +} + +double +YansWifiPhy::GetPowerDbm (uint8_t power) const +{ + NS_ASSERT (m_txPowerBaseDbm <= m_txPowerEndDbm); + NS_ASSERT (m_nTxPower > 0); + double dbm; + if (m_nTxPower > 1) + { + dbm = m_txPowerBaseDbm + power * (m_txPowerEndDbm - m_txPowerBaseDbm) / (m_nTxPower - 1); + } + else + { + NS_ASSERT_MSG (m_txPowerBaseDbm == m_txPowerEndDbm, "cannot have TxPowerEnd != TxPowerStart with TxPowerLevels == 1"); + dbm = m_txPowerBaseDbm; + } + return dbm; +} + +void +YansWifiPhy::EndReceive (Ptr<Packet> packet, enum WifiPreamble preamble, struct mpduInfo aMpdu, Ptr<InterferenceHelper::Event> event) +{ + NS_LOG_FUNCTION (this << packet << event); + NS_ASSERT (IsStateRx ()); + NS_ASSERT (event->GetEndTime () == Simulator::Now ()); + + struct InterferenceHelper::SnrPer snrPer; + snrPer = m_interference.CalculatePlcpPayloadSnrPer (event); + m_interference.NotifyRxEnd (); + + if (m_plcpSuccess == true) + { + NS_LOG_DEBUG ("mode=" << (event->GetPayloadMode ().GetDataRate (event->GetTxVector ().GetChannelWidth (), event->GetTxVector ().IsShortGuardInterval (), 1)) << + ", snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per << ", size=" << packet->GetSize ()); + + //*******added for RSSI tag********* + RssiTag tag; // The tag that I defined. It holds signal RSSI + double rssi = event->GetRxPowerW (); // +30 to convert dBW to dBm + tag.Set(rssi); + packet->RemovePacketTag (tag); + packet->AddPacketTag (tag); + //***************end************* + + + if (m_random->GetValue () > snrPer.per) + { + NotifyRxEnd (packet); + uint32_t dataRate500KbpsUnits; + if ((event->GetPayloadMode ().GetModulationClass () == WIFI_MOD_CLASS_HT) || (event->GetPayloadMode ().GetModulationClass () == WIFI_MOD_CLASS_VHT)) + { + dataRate500KbpsUnits = 128 + event->GetPayloadMode ().GetMcsValue (); + } + else + { + dataRate500KbpsUnits = event->GetPayloadMode ().GetDataRate (event->GetTxVector ().GetChannelWidth (), event->GetTxVector ().IsShortGuardInterval (), 1) * event->GetTxVector ().GetNss () / 500000; + } + struct signalNoiseDbm signalNoise; + signalNoise.signal = RatioToDb (event->GetRxPowerW ()) + 30; + signalNoise.noise = RatioToDb (event->GetRxPowerW () / snrPer.snr) - GetRxNoiseFigure () + 30; + NotifyMonitorSniffRx (packet, (uint16_t)GetChannelFrequencyMhz (), GetChannelNumber (), dataRate500KbpsUnits, event->GetPreambleType (), event->GetTxVector (), aMpdu, signalNoise); + m_state->SwitchFromRxEndOk (packet, snrPer.snr, event->GetTxVector (), event->GetPreambleType ()); + } + else + { + /* failure. */ + NotifyRxDrop (packet); + m_state->SwitchFromRxEndError (packet, snrPer.snr); + } + } + else + { + m_state->SwitchFromRxEndError (packet, snrPer.snr); + } + + if (preamble == WIFI_PREAMBLE_NONE && aMpdu.packetType == 2) + { + m_plcpSuccess = false; + } +} + +int64_t +YansWifiPhy::AssignStreams (int64_t stream) +{ + NS_LOG_FUNCTION (this << stream); + m_random->SetStream (stream); + return 1; +} + +void +YansWifiPhy::SetFrequency (uint32_t freq) +{ + m_channelStartingFrequency = freq; +} + +void +YansWifiPhy::SetNumberOfTransmitAntennas (uint32_t tx) +{ + m_numberOfTransmitters = tx; +} + +void +YansWifiPhy::SetNumberOfReceiveAntennas (uint32_t rx) +{ + m_numberOfReceivers = rx; +} + +void +YansWifiPhy::SetLdpc (bool Ldpc) +{ + m_ldpc = Ldpc; +} + +void +YansWifiPhy::SetStbc (bool stbc) +{ + m_stbc = stbc; +} + +void +YansWifiPhy::SetGreenfield (bool greenfield) +{ + m_greenfield = greenfield; +} + +bool +YansWifiPhy::GetGuardInterval (void) const +{ + return m_guardInterval; +} + +void +YansWifiPhy::SetGuardInterval (bool guardInterval) +{ + m_guardInterval = guardInterval; +} + +uint32_t +YansWifiPhy::GetFrequency (void) const +{ + return m_channelStartingFrequency; +} + +uint32_t +YansWifiPhy::GetNumberOfTransmitAntennas (void) const +{ + return m_numberOfTransmitters; +} + +uint32_t +YansWifiPhy::GetNumberOfReceiveAntennas (void) const +{ + return m_numberOfReceivers; +} + +bool +YansWifiPhy::GetLdpc (void) const +{ + return m_ldpc; +} + +bool +YansWifiPhy::GetStbc (void) const +{ + return m_stbc; +} + +bool +YansWifiPhy::GetGreenfield (void) const +{ + return m_greenfield; +} + +void +YansWifiPhy::SetChannelWidth (uint32_t channelwidth) +{ + NS_ASSERT_MSG (channelwidth == 5 || channelwidth == 10 || channelwidth == 20 || channelwidth == 22 || channelwidth == 40 || channelwidth == 80 || channelwidth == 160, "wrong channel width value"); + m_channelWidth = channelwidth; +} + +uint32_t +YansWifiPhy::GetChannelWidth (void) const +{ + return m_channelWidth; +} + +uint32_t +YansWifiPhy::GetNBssMembershipSelectors (void) const +{ + return m_bssMembershipSelectorSet.size (); +} + +uint32_t +YansWifiPhy::GetBssMembershipSelector (uint32_t selector) const +{ + return m_bssMembershipSelectorSet[selector]; +} + +WifiModeList +YansWifiPhy::GetMembershipSelectorModes (uint32_t selector) +{ + uint32_t id = GetBssMembershipSelector (selector); + WifiModeList supportedmodes; + if (id == HT_PHY || id == VHT_PHY) + { + //mandatory MCS 0 to 7 + supportedmodes.push_back (WifiPhy::GetHtMcs0 ()); + supportedmodes.push_back (WifiPhy::GetHtMcs1 ()); + supportedmodes.push_back (WifiPhy::GetHtMcs2 ()); + supportedmodes.push_back (WifiPhy::GetHtMcs3 ()); + supportedmodes.push_back (WifiPhy::GetHtMcs4 ()); + supportedmodes.push_back (WifiPhy::GetHtMcs5 ()); + supportedmodes.push_back (WifiPhy::GetHtMcs6 ()); + supportedmodes.push_back (WifiPhy::GetHtMcs7 ()); + } + if (id == VHT_PHY) + { + //mandatory MCS 0 to 9 + supportedmodes.push_back (WifiPhy::GetVhtMcs0 ()); + supportedmodes.push_back (WifiPhy::GetVhtMcs1 ()); + supportedmodes.push_back (WifiPhy::GetVhtMcs2 ()); + supportedmodes.push_back (WifiPhy::GetVhtMcs3 ()); + supportedmodes.push_back (WifiPhy::GetVhtMcs4 ()); + supportedmodes.push_back (WifiPhy::GetVhtMcs5 ()); + supportedmodes.push_back (WifiPhy::GetVhtMcs6 ()); + supportedmodes.push_back (WifiPhy::GetVhtMcs7 ()); + supportedmodes.push_back (WifiPhy::GetVhtMcs8 ()); + supportedmodes.push_back (WifiPhy::GetVhtMcs9 ()); + } + return supportedmodes; +} + +uint8_t +YansWifiPhy::GetNMcs (void) const +{ + return m_deviceMcsSet.size (); +} + +WifiMode +YansWifiPhy::GetMcs (uint8_t mcs) const +{ + return m_deviceMcsSet[mcs]; +} + +} //namespace ns3 |