wifi: (fixes #2552) Remove remaining code duplication between Yans and Spectrum

This commit is contained in:
Sébastien Deronne
2016-11-27 19:27:15 +01:00
parent e71851491d
commit c7a5c8ac6f
12 changed files with 719 additions and 1183 deletions

View File

@@ -46,6 +46,7 @@ Bugs fixed
- Bug 2545 - Optimized build fails for flow-monitor
- Bug 2547 - dead assignments on various tcp congestion controls
- Bug 2551 - wifi preamble should be part of TXVECTOR
- Bug 2552 - Remove code duplication between Yans and Spectrum
Known issues
------------

View File

@@ -33,11 +33,9 @@
#include "ns3/log.h"
#include "ns3/double.h"
#include "ns3/boolean.h"
#include "ampdu-tag.h"
#include "wifi-spectrum-signal-parameters.h"
#include "wifi-phy-tag.h"
#include "ns3/antenna-model.h"
#include <cmath>
#include "wifi-utils.h"
namespace ns3 {
@@ -98,112 +96,6 @@ SpectrumWifiPhy::DoInitialize (void)
}
}
bool
SpectrumWifiPhy::DoChannelSwitch (uint16_t nch)
{
if (IsInitialized () == false)
{
//this is not channel switch, this is initialization
NS_LOG_DEBUG ("start at channel " << nch);
return true;
}
NS_ASSERT (!IsStateSwitching ());
switch (m_state->GetState ())
{
case SpectrumWifiPhy::RX:
NS_LOG_DEBUG ("drop packet because of channel switching while reception");
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
goto switchChannel;
break;
case SpectrumWifiPhy::TX:
NS_LOG_DEBUG ("channel switching postponed until end of current transmission");
Simulator::Schedule (GetDelayUntilIdle (), &WifiPhy::SetChannelNumber, this, nch);
break;
case SpectrumWifiPhy::CCA_BUSY:
case SpectrumWifiPhy::IDLE:
goto switchChannel;
break;
case SpectrumWifiPhy::SLEEP:
NS_LOG_DEBUG ("channel switching ignored in sleep mode");
break;
default:
NS_ASSERT (false);
break;
}
return false;
switchChannel:
NS_LOG_DEBUG ("switching channel " << GetChannelNumber () << " -> " << nch);
m_rxSpectrumModel = WifiSpectrumValueHelper::GetSpectrumModel (GetFrequency (), GetChannelWidth ());
m_state->SwitchToChannelSwitching (GetChannelSwitchDelay ());
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.
*/
return true;
}
bool
SpectrumWifiPhy::DoFrequencySwitch (uint32_t frequency)
{
if (IsInitialized () == false)
{
//this is not channel switch, this is initialization
NS_LOG_DEBUG ("start at frequency " << frequency);
return true;
}
NS_ASSERT (!IsStateSwitching ());
switch (m_state->GetState ())
{
case SpectrumWifiPhy::RX:
NS_LOG_DEBUG ("drop packet because of channel/frequency switching while reception");
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
goto switchFrequency;
break;
case SpectrumWifiPhy::TX:
NS_LOG_DEBUG ("channel/frequency switching postponed until end of current transmission");
Simulator::Schedule (GetDelayUntilIdle (), &WifiPhy::SetFrequency, this, frequency);
break;
case SpectrumWifiPhy::CCA_BUSY:
case SpectrumWifiPhy::IDLE:
goto switchFrequency;
break;
case SpectrumWifiPhy::SLEEP:
NS_LOG_DEBUG ("frequency switching ignored in sleep mode");
break;
default:
NS_ASSERT (false);
break;
}
return false;
switchFrequency:
NS_LOG_DEBUG ("switching frequency " << GetFrequency () << " -> " << frequency);
m_rxSpectrumModel = WifiSpectrumValueHelper::GetSpectrumModel (GetFrequency (), GetChannelWidth ());
m_state->SwitchToChannelSwitching (GetChannelSwitchDelay ());
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.
*/
return true;
}
Ptr<const SpectrumModel>
SpectrumWifiPhy::GetRxSpectrumModel () const
{
@@ -240,12 +132,6 @@ SpectrumWifiPhy::SetChannel (Ptr<SpectrumChannel> channel)
m_channel = channel;
}
void
SpectrumWifiPhy::SetPacketReceivedCallback (RxCallback callback)
{
m_rxCallback = callback;
}
void
SpectrumWifiPhy::AddOperationalChannel (uint16_t channelNumber)
{
@@ -273,80 +159,6 @@ SpectrumWifiPhy::ClearOperationalChannelList ()
m_operationalChannelList.clear ();
}
void
SpectrumWifiPhy::SetSleepMode (void)
{
NS_LOG_FUNCTION (this);
switch (m_state->GetState ())
{
case SpectrumWifiPhy::TX:
NS_LOG_DEBUG ("setting sleep mode postponed until end of current transmission");
Simulator::Schedule (GetDelayUntilIdle (), &SpectrumWifiPhy::SetSleepMode, this);
break;
case SpectrumWifiPhy::RX:
NS_LOG_DEBUG ("setting sleep mode postponed until end of current reception");
Simulator::Schedule (GetDelayUntilIdle (), &SpectrumWifiPhy::SetSleepMode, this);
break;
case SpectrumWifiPhy::SWITCHING:
NS_LOG_DEBUG ("setting sleep mode postponed until end of channel switching");
Simulator::Schedule (GetDelayUntilIdle (), &SpectrumWifiPhy::SetSleepMode, this);
break;
case SpectrumWifiPhy::CCA_BUSY:
case SpectrumWifiPhy::IDLE:
NS_LOG_DEBUG ("setting sleep mode");
m_state->SwitchToSleep ();
break;
case SpectrumWifiPhy::SLEEP:
NS_LOG_DEBUG ("already in sleep mode");
break;
default:
NS_ASSERT (false);
break;
}
}
void
SpectrumWifiPhy::ResumeFromSleep (void)
{
NS_LOG_FUNCTION (this);
switch (m_state->GetState ())
{
case SpectrumWifiPhy::TX:
case SpectrumWifiPhy::RX:
case SpectrumWifiPhy::IDLE:
case SpectrumWifiPhy::CCA_BUSY:
case SpectrumWifiPhy::SWITCHING:
{
NS_LOG_DEBUG ("not in sleep mode, there is nothing to resume");
break;
}
case SpectrumWifiPhy::SLEEP:
{
NS_LOG_DEBUG ("resuming from sleep mode");
Time delayUntilCcaEnd = m_interference.GetEnergyDuration (DbmToW (GetCcaMode1Threshold ()));
m_state->SwitchFromSleep (delayUntilCcaEnd);
break;
}
default:
{
NS_ASSERT (false);
break;
}
}
}
void
SpectrumWifiPhy::SetReceiveOkCallback (RxOkCallback callback)
{
m_state->SetReceiveOkCallback (callback);
}
void
SpectrumWifiPhy::SetReceiveErrorCallback (RxErrorCallback callback)
{
m_state->SetReceiveErrorCallback (callback);
}
void
SpectrumWifiPhy::StartRx (Ptr<SpectrumSignalParameters> rxParams)
{
@@ -391,207 +203,7 @@ SpectrumWifiPhy::StartRx (Ptr<SpectrumSignalParameters> rxParams)
NS_LOG_INFO ("Received Wi-Fi signal");
Ptr<Packet> packet = wifiRxParams->packet->Copy ();
WifiPhyTag tag;
bool found = packet->PeekPacketTag (tag);
if (!found)
{
NS_FATAL_ERROR ("Received Wi-Fi Spectrum Signal with no WifiPhyTag");
return;
}
WifiTxVector txVector = tag.GetWifiTxVector ();
if (txVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT
&& (txVector.GetNss () != (1 + (txVector.GetMode ().GetMcsValue () / 8))))
{
NS_FATAL_ERROR ("MCS value does not match NSS value: MCS = " << (uint16_t)txVector.GetMode ().GetMcsValue () << ", NSS = " << (uint16_t)txVector.GetNss ());
}
if (txVector.GetNss () > GetMaxSupportedRxSpatialStreams ())
{
NS_FATAL_ERROR ("Reception ends in failure because of an unsupported number of spatial streams");
}
WifiPreamble preamble = txVector.GetPreambleType ();
MpduType mpdutype = tag.GetMpduType ();
// At this point forward, processing parallels that of
// YansWifiPhy::StartReceivePreambleAndHeader ()
AmpduTag ampduTag;
Time endRx = Simulator::Now () + rxDuration;
Time preambleAndHeaderDuration = CalculatePlcpPreambleAndHeaderDuration (txVector);
Ptr<InterferenceHelper::Event> event;
event = m_interference.Add (packet->GetSize (),
txVector,
rxDuration,
rxPowerW);
switch (m_state->GetState ())
{
case SpectrumWifiPhy::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.
SwitchMaybeToCcaBusy ();
return;
}
break;
case SpectrumWifiPhy::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.
SwitchMaybeToCcaBusy ();
return;
}
break;
case SpectrumWifiPhy::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.
SwitchMaybeToCcaBusy ();
return;
}
break;
case SpectrumWifiPhy::CCA_BUSY:
case SpectrumWifiPhy::IDLE:
if (rxPowerW > GetEdThresholdW ()) //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);
SwitchMaybeToCcaBusy ();
return;
}
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);
SwitchMaybeToCcaBusy ();
return;
}
else if (preamble != WIFI_PREAMBLE_NONE && packet->PeekPacketTag (ampduTag) && m_mpdusNum == 0)
{
//received the first MPDU in an MPDU
m_mpdusNum = ampduTag.GetRemainingNbOfMpdus () - 1;
m_rxMpduReferenceNumber++;
}
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.GetRemainingNbOfMpdus () < m_mpdusNum)
{
NS_LOG_DEBUG ("Missing MPDU from the A-MPDU " << m_mpdusNum - ampduTag.GetRemainingNbOfMpdus ());
m_mpdusNum = ampduTag.GetRemainingNbOfMpdus ();
}
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, &SpectrumWifiPhy::StartReceivePacket, this,
packet, txVector, mpdutype, event);
}
NS_ASSERT (m_endRxEvent.IsExpired ());
m_endRxEvent = Simulator::Schedule (rxDuration, &SpectrumWifiPhy::EndReceive, this,
packet, preamble, mpdutype, event);
}
else
{
NS_LOG_DEBUG ("drop packet because signal power too Small (" <<
rxPowerW << "<" << GetEdThresholdW () << ")");
NotifyRxDrop (packet);
m_plcpSuccess = false;
SwitchMaybeToCcaBusy ();
return;
}
break;
case SpectrumWifiPhy::SLEEP:
NS_LOG_DEBUG ("drop packet because in sleep mode");
NotifyRxDrop (packet);
m_plcpSuccess = false;
break;
}
return;
}
void
SpectrumWifiPhy::StartReceivePacket (Ptr<Packet> packet,
WifiTxVector txVector,
MpduType mpdutype,
Ptr<InterferenceHelper::Event> event)
{
NS_LOG_FUNCTION (this << packet << txVector.GetMode () << txVector.GetPreambleType () << (uint32_t)mpdutype);
NS_ASSERT (IsStateRx ());
NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
AmpduTag ampduTag;
WifiMode txMode = txVector.GetMode ();
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;
}
StartReceivePreambleAndHeader (packet, rxPowerW, rxDuration);
}
Ptr<WifiSpectrumPhyInterface>
@@ -652,65 +264,10 @@ SpectrumWifiPhy::GetTxPowerSpectralDensity (uint32_t centerFrequency, uint32_t c
}
void
SpectrumWifiPhy::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, MpduType mpdutype)
SpectrumWifiPhy::StartTx (Ptr<Packet> packet, WifiTxVector txVector, Time txDuration)
{
NS_LOG_FUNCTION (this << packet << txVector.GetMode ()
<< txVector.GetMode ().GetDataRate (txVector)
<< txVector.GetPreambleType ()
<< (uint32_t)txVector.GetTxPowerLevel ()
<< (uint32_t)mpdutype);
/* 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 (txVector.GetNss () > GetMaxSupportedTxSpatialStreams ())
{
NS_FATAL_ERROR ("Unsupported number of spatial streams!");
}
if (m_state->IsStateSleep ())
{
NS_LOG_DEBUG ("Dropping packet because in sleep mode");
NotifyTxDrop (packet);
return;
}
Time txDuration = CalculateTxDuration (packet->GetSize (), txVector, GetFrequency (), mpdutype, 1);
NS_ASSERT (txDuration > NanoSeconds (0));
if (m_state->IsStateRx ())
{
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_interference.NotifyRxEnd ();
}
NotifyTxBegin (packet);
if ((mpdutype == MPDU_IN_AGGREGATE) && (txVector.GetPreambleType () != WIFI_PREAMBLE_NONE))
{
//send the first MPDU in an MPDU
m_txMpduReferenceNumber++;
}
MpduInfo aMpdu;
aMpdu.type = mpdutype;
aMpdu.mpduRefNumber = m_txMpduReferenceNumber;
NotifyMonitorSniffTx (packet, (uint16_t) GetFrequency (), GetChannelNumber (), txVector, aMpdu);
m_state->SwitchToTx (txDuration, packet, GetPowerDbm (txVector.GetTxPowerLevel ()), txVector);
//
// Spectrum elements added here
//
Ptr<Packet> newPacket = packet->Copy (); // obtain non-const Packet
WifiPhyTag oldtag;
newPacket->RemovePacketTag (oldtag);
WifiPhyTag tag (txVector, mpdutype);
newPacket->AddPacketTag (tag);
NS_LOG_DEBUG ("Transmission signal power before antenna gain: " << GetPowerDbm (txVector.GetTxPowerLevel ()) << " dBm");
NS_LOG_DEBUG ("Start transmission: signal power before antenna gain=" << GetPowerDbm (txVector.GetTxPowerLevel ()) << "dBm");
double txPowerWatts = DbmToW (GetPowerDbm (txVector.GetTxPowerLevel ()) + GetTxGain ());
Ptr<SpectrumValue> txPowerSpectrum = GetTxPowerSpectralDensity (GetFrequency (), GetChannelWidth (), txPowerWatts);
Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters> ();
txParams->duration = txDuration;
@@ -718,80 +275,10 @@ SpectrumWifiPhy::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, Mp
NS_ASSERT_MSG (m_wifiSpectrumPhyInterface, "SpectrumPhy() is not set; maybe forgot to call CreateWifiSpectrumPhyInterface?");
txParams->txPhy = m_wifiSpectrumPhyInterface->GetObject<SpectrumPhy> ();
txParams->txAntenna = m_antenna;
txParams->packet = newPacket;
txParams->packet = packet;
NS_LOG_DEBUG ("Starting transmission with power " << WToDbm (txPowerWatts) << " dBm on channel " << GetChannelNumber ());
NS_LOG_DEBUG ("Starting transmission with integrated spectrum power " << WToDbm (Integral (*txPowerSpectrum)) << " dBm; spectrum model Uid: " << txPowerSpectrum->GetSpectrumModel ()->GetUid ());
m_channel->StartTx (txParams);
}
void
SpectrumWifiPhy::RegisterListener (WifiPhyListener *listener)
{
m_state->RegisterListener (listener);
}
void
SpectrumWifiPhy::UnregisterListener (WifiPhyListener *listener)
{
m_state->UnregisterListener (listener);
}
void
SpectrumWifiPhy::EndReceive (Ptr<Packet> packet, WifiPreamble preamble, MpduType mpdutype, Ptr<InterferenceHelper::Event> event)
{
NS_LOG_FUNCTION (this << packet << event);
NS_ASSERT (IsStateRx ());
NS_ASSERT (event->GetEndTime () == Simulator::Now ());
InterferenceHelper::SnrPer snrPer;
snrPer = m_interference.CalculatePlcpPayloadSnrPer (event);
m_interference.NotifyRxEnd ();
bool rxSucceeded;
if (m_plcpSuccess == true)
{
NS_LOG_DEBUG ("mode=" << (event->GetPayloadMode ().GetDataRate (event->GetTxVector ())) <<
", snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per << ", size=" << packet->GetSize ());
if (m_random->GetValue () > snrPer.per)
{
NotifyRxEnd (packet);
SignalNoiseDbm signalNoise;
signalNoise.signal = RatioToDb (event->GetRxPowerW ()) + 30;
signalNoise.noise = RatioToDb (event->GetRxPowerW () / snrPer.snr) - GetRxNoiseFigure () + 30;
MpduInfo aMpdu;
aMpdu.type = mpdutype;
aMpdu.mpduRefNumber = m_rxMpduReferenceNumber;
NotifyMonitorSniffRx (packet, (uint16_t) GetFrequency (), GetChannelNumber (), event->GetTxVector (), aMpdu, signalNoise);
m_state->SwitchFromRxEndOk (packet, snrPer.snr, event->GetTxVector ());
rxSucceeded = true;
}
else
{
/* failure. */
NotifyRxDrop (packet);
m_state->SwitchFromRxEndError (packet, snrPer.snr);
rxSucceeded = false;
}
if (!m_rxCallback.IsNull ())
{
m_rxCallback (rxSucceeded);
}
}
else
{
m_state->SwitchFromRxEndError (packet, snrPer.snr);
if (!m_rxCallback.IsNull ())
{
m_rxCallback (false);
}
}
if (preamble == WIFI_PREAMBLE_NONE && mpdutype == LAST_MPDU_IN_AGGREGATE)
{
m_plcpSuccess = false;
}
}
} //namespace ns3

View File

@@ -80,19 +80,6 @@ public:
*/
void ClearOperationalChannelList (void);
/**
* Starting receiving the payload of a packet (i.e. the first bit of the packet has arrived).
*
* \param packet the arriving packet
* \param txVector the TXVECTOR of the arriving packet
* \param mpdutype the type of the MPDU as defined in WifiPhy::MpduType.
* \param event the corresponding event of the first time the packet arrives
*/
void StartReceivePacket (Ptr<Packet> packet,
WifiTxVector txVector,
MpduType mpdutype,
Ptr<InterferenceHelper::Event> event);
/**
* Input method for delivering a signal from the spectrum channel
* and low-level Phy interface to this SpectrumWifiPhy instance.
@@ -100,6 +87,16 @@ public:
* \param rxParams Input signal parameters
*/
void StartRx (Ptr<SpectrumSignalParameters> rxParams);
/**
* \param packet the packet to send
* \param txVector the TXVECTOR that has tx parameters such as mode, the transmission mode to use to send
* this packet, and txPowerLevel, a power level to use to send this packet. The real transmission
* power is calculated as txPowerMin + txPowerLevel * (txPowerMax - txPowerMin) / nTxLevels
* \param txDuration duration of the transmission.
*/
void StartTx (Ptr<Packet> packet, WifiTxVector txVector, Time txDuration);
/**
* Method to encapsulate the creation of the WifiSpectrumPhyInterface
* object (used to bind the WifiSpectrumPhy to a SpectrumChannel) and
@@ -136,19 +133,6 @@ public:
* returned, it means that any model will be accepted.
*/
Ptr<const SpectrumModel> GetRxSpectrumModel () const;
/**
* Callback invoked at the end of a frame reception, to notify whether
* the frame was received successfully (true) or not (false)
*/
typedef Callback<void,bool> RxCallback;
/**
* Set the packet received callback (invoked at the end of a frame
* reception), to notify whether the frame was received successfully
* or not.
*
* \param callback the function to hook to the callback
*/
void SetPacketReceivedCallback (RxCallback callback);
/**
* Callback invoked when the Phy model starts to process a signal
@@ -160,33 +144,16 @@ public:
*/
typedef void (* SignalArrivalCallback) (bool signalType, uint32_t senderNodeId, double rxPower, Time duration);
virtual void SetReceiveOkCallback (WifiPhy::RxOkCallback callback);
virtual void SetReceiveErrorCallback (WifiPhy::RxErrorCallback callback);
virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, MpduType mpdutype = NORMAL_MPDU);
virtual void RegisterListener (WifiPhyListener *listener);
virtual void UnregisterListener (WifiPhyListener *listener);
virtual void SetSleepMode (void);
virtual void ResumeFromSleep (void);
virtual Ptr<WifiChannel> GetChannel (void) const;
protected:
// Inherited
virtual void DoDispose (void);
virtual void DoInitialize (void);
virtual bool DoChannelSwitch (uint16_t id);
virtual bool DoFrequencySwitch (uint32_t frequency);
private:
/**
* The last bit of the packet has arrived.
*
* \param packet the packet that the last bit has arrived
* \param preamble the preamble of the arriving packet
* \param mpdutype the type of the MPDU as defined in WifiPhy::MpduType.
* \param event the corresponding event of the first time the packet arrives
*/
void EndReceive (Ptr<Packet> packet, WifiPreamble preamble, MpduType mpdutype, Ptr<InterferenceHelper::Event> event);
/**
* \param centerFrequency center frequency (MHz)
* \param channelWidth channel width (MHz) of the channel
@@ -204,7 +171,6 @@ private:
Ptr<WifiSpectrumPhyInterface> m_wifiSpectrumPhyInterface;
Ptr<AntennaModel> m_antenna;
mutable Ptr<const SpectrumModel> m_rxSpectrumModel;
RxCallback m_rxCallback;
bool m_disableWifiReception; //!< forces this Phy to fail to sync on any signal
TracedCallback<bool, uint32_t, double, Time> m_signalCb;

View File

@@ -34,7 +34,9 @@
#include "ns3/pointer.h"
#include "ns3/trace-source-accessor.h"
#include "ns3/fatal-error.h"
#include <cmath>
#include "wifi-phy-tag.h"
#include "ampdu-tag.h"
#include "wifi-utils.h"
namespace ns3 {
@@ -415,6 +417,30 @@ WifiPhy::DoInitialize (void)
InitializeFrequencyChannelNumber ();
}
void
WifiPhy::SetReceiveOkCallback (RxOkCallback callback)
{
m_state->SetReceiveOkCallback (callback);
}
void
WifiPhy::SetReceiveErrorCallback (RxErrorCallback callback)
{
m_state->SetReceiveErrorCallback (callback);
}
void
WifiPhy::RegisterListener (WifiPhyListener *listener)
{
m_state->RegisterListener (listener);
}
void
WifiPhy::UnregisterListener (WifiPhyListener *listener)
{
m_state->UnregisterListener (listener);
}
void
WifiPhy::InitializeFrequencyChannelNumber (void)
{
@@ -1364,15 +1390,169 @@ WifiPhy::GetChannelNumber (void) const
bool
WifiPhy::DoChannelSwitch (uint16_t nch)
{
if (!IsInitialized ())
{
//this is not channel switch, this is initialization
NS_LOG_DEBUG ("initialize to channel " << nch);
return true;
}
NS_ASSERT (!IsStateSwitching ());
switch (m_state->GetState ())
{
case WifiPhy::RX:
NS_LOG_DEBUG ("drop packet because of channel switching while reception");
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
goto switchChannel;
break;
case WifiPhy::TX:
NS_LOG_DEBUG ("channel switching postponed until end of current transmission");
Simulator::Schedule (GetDelayUntilIdle (), &WifiPhy::SetChannelNumber, this, nch);
break;
case WifiPhy::CCA_BUSY:
case WifiPhy::IDLE:
goto switchChannel;
break;
case WifiPhy::SLEEP:
NS_LOG_DEBUG ("channel switching ignored in sleep mode");
break;
default:
NS_ASSERT (false);
break;
}
return false;
switchChannel:
NS_LOG_DEBUG ("switching channel " << GetChannelNumber () << " -> " << nch);
m_state->SwitchToChannelSwitching (GetChannelSwitchDelay ());
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.
*/
return true;
}
bool
WifiPhy::DoFrequencySwitch (uint32_t frequency)
{
if (!IsInitialized ())
{
//this is not channel switch, this is initialization
NS_LOG_DEBUG ("start at frequency " << frequency);
return true;
}
NS_ASSERT (!IsStateSwitching ());
switch (m_state->GetState ())
{
case WifiPhy::RX:
NS_LOG_DEBUG ("drop packet because of channel/frequency switching while reception");
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
goto switchFrequency;
break;
case WifiPhy::TX:
NS_LOG_DEBUG ("channel/frequency switching postponed until end of current transmission");
Simulator::Schedule (GetDelayUntilIdle (), &WifiPhy::SetFrequency, this, frequency);
break;
case WifiPhy::CCA_BUSY:
case WifiPhy::IDLE:
goto switchFrequency;
break;
case WifiPhy::SLEEP:
NS_LOG_DEBUG ("frequency switching ignored in sleep mode");
break;
default:
NS_ASSERT (false);
break;
}
return false;
switchFrequency:
NS_LOG_DEBUG ("switching frequency " << GetFrequency () << " -> " << frequency);
m_state->SwitchToChannelSwitching (GetChannelSwitchDelay ());
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.
*/
return true;
}
void
WifiPhy::SetSleepMode (void)
{
NS_LOG_FUNCTION (this);
switch (m_state->GetState ())
{
case WifiPhy::TX:
NS_LOG_DEBUG ("setting sleep mode postponed until end of current transmission");
Simulator::Schedule (GetDelayUntilIdle (), &WifiPhy::SetSleepMode, this);
break;
case WifiPhy::RX:
NS_LOG_DEBUG ("setting sleep mode postponed until end of current reception");
Simulator::Schedule (GetDelayUntilIdle (), &WifiPhy::SetSleepMode, this);
break;
case WifiPhy::SWITCHING:
NS_LOG_DEBUG ("setting sleep mode postponed until end of channel switching");
Simulator::Schedule (GetDelayUntilIdle (), &WifiPhy::SetSleepMode, this);
break;
case WifiPhy::CCA_BUSY:
case WifiPhy::IDLE:
NS_LOG_DEBUG ("setting sleep mode");
m_state->SwitchToSleep ();
break;
case WifiPhy::SLEEP:
NS_LOG_DEBUG ("already in sleep mode");
break;
default:
NS_ASSERT (false);
break;
}
}
void
WifiPhy::ResumeFromSleep (void)
{
NS_LOG_FUNCTION (this);
switch (m_state->GetState ())
{
case WifiPhy::TX:
case WifiPhy::RX:
case WifiPhy::IDLE:
case WifiPhy::CCA_BUSY:
case WifiPhy::SWITCHING:
{
NS_LOG_DEBUG ("not in sleep mode, there is nothing to resume");
break;
}
case WifiPhy::SLEEP:
{
NS_LOG_DEBUG ("resuming from sleep mode");
Time delayUntilCcaEnd = m_interference.GetEnergyDuration (DbmToW (GetCcaMode1Threshold ()));
m_state->SwitchFromSleep (delayUntilCcaEnd);
break;
}
default:
{
NS_ASSERT (false);
break;
}
}
}
WifiMode
WifiPhy::GetHtPlcpHeaderMode (WifiMode payloadMode)
{
@@ -2026,6 +2206,323 @@ WifiPhy::NotifyMonitorSniffTx (Ptr<const Packet> packet, uint16_t channelFreqMhz
m_phyMonitorSniffTxTrace (packet, channelFreqMhz, channelNumber, txVector, aMpdu);
}
void
WifiPhy::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, MpduType mpdutype)
{
NS_LOG_FUNCTION (this << packet << txVector.GetMode ()
<< txVector.GetMode ().GetDataRate (txVector)
<< txVector.GetPreambleType ()
<< (uint32_t)txVector.GetTxPowerLevel ()
<< (uint32_t)mpdutype);
/* 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 (txVector.GetNss () > GetMaxSupportedTxSpatialStreams ())
{
NS_FATAL_ERROR ("Unsupported number of spatial streams!");
}
if (m_state->IsStateSleep ())
{
NS_LOG_DEBUG ("Dropping packet because in sleep mode");
NotifyTxDrop (packet);
return;
}
Time txDuration = CalculateTxDuration (packet->GetSize (), txVector, GetFrequency (), mpdutype, 1);
NS_ASSERT (txDuration > NanoSeconds (0));
if (m_state->IsStateRx ())
{
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_interference.NotifyRxEnd ();
}
NotifyTxBegin (packet);
if ((mpdutype == MPDU_IN_AGGREGATE) && (txVector.GetPreambleType () != WIFI_PREAMBLE_NONE))
{
//send the first MPDU in an MPDU
m_txMpduReferenceNumber++;
}
MpduInfo aMpdu;
aMpdu.type = mpdutype;
aMpdu.mpduRefNumber = m_txMpduReferenceNumber;
NotifyMonitorSniffTx (packet, (uint16_t) GetFrequency (), GetChannelNumber (), txVector, aMpdu);
m_state->SwitchToTx (txDuration, packet, GetPowerDbm (txVector.GetTxPowerLevel ()), txVector);
Ptr<Packet> newPacket = packet->Copy (); // obtain non-const Packet
WifiPhyTag oldtag;
newPacket->RemovePacketTag (oldtag);
WifiPhyTag tag (txVector, mpdutype);
newPacket->AddPacketTag (tag);
StartTx (newPacket, txVector, txDuration);
}
void
WifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerW, 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 << WToDbm (rxPowerW) << rxDuration);
AmpduTag ampduTag;
Time endRx = Simulator::Now () + rxDuration;
WifiPhyTag tag;
bool found = packet->RemovePacketTag (tag);
if (!found)
{
NS_FATAL_ERROR ("Received Wi-Fi Signal with no WifiPhyTag");
return;
}
WifiTxVector txVector = tag.GetWifiTxVector ();
if (txVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT
&& (txVector.GetNss () != (1 + (txVector.GetMode ().GetMcsValue () / 8))))
{
NS_FATAL_ERROR ("MCS value does not match NSS value: MCS = " << (uint16_t)txVector.GetMode ().GetMcsValue () << ", NSS = " << (uint16_t)txVector.GetNss ());
}
if (txVector.GetNss () > GetMaxSupportedRxSpatialStreams ())
{
NS_FATAL_ERROR ("Reception ends in failure because of an unsupported number of spatial streams");
}
WifiPreamble preamble = txVector.GetPreambleType ();
MpduType mpdutype = tag.GetMpduType ();
Time preambleAndHeaderDuration = CalculatePlcpPreambleAndHeaderDuration (txVector);
Ptr<InterferenceHelper::Event> event;
event = m_interference.Add (packet->GetSize (),
txVector,
rxDuration,
rxPowerW);
switch (m_state->GetState ())
{
case WifiPhy::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 WifiPhy::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 WifiPhy::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 WifiPhy::CCA_BUSY:
case WifiPhy::IDLE:
if (rxPowerW > GetEdThresholdW ()) //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 || m_plcpSuccess == false))
{
m_plcpSuccess = false;
m_mpdusNum = 0;
NS_LOG_DEBUG ("drop packet because no PLCP preamble/header 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.GetRemainingNbOfMpdus ();
m_rxMpduReferenceNumber++;
}
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.GetRemainingNbOfMpdus () < (m_mpdusNum - 1))
{
NS_LOG_DEBUG ("Missing MPDU from the A-MPDU " << m_mpdusNum - ampduTag.GetRemainingNbOfMpdus ());
m_mpdusNum = ampduTag.GetRemainingNbOfMpdus ();
}
else
{
m_mpdusNum--;
}
}
else if (preamble != WIFI_PREAMBLE_NONE && packet->PeekPacketTag (ampduTag) && m_mpdusNum > 0)
{
NS_LOG_DEBUG ("New A-MPDU started while " << m_mpdusNum << " MPDUs from previous are lost");
m_mpdusNum = ampduTag.GetRemainingNbOfMpdus ();
}
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, &WifiPhy::StartReceivePacket, this,
packet, txVector, mpdutype, event);
}
NS_ASSERT (m_endRxEvent.IsExpired ());
m_endRxEvent = Simulator::Schedule (rxDuration, &WifiPhy::EndReceive, this,
packet, preamble, mpdutype, event);
}
else
{
NS_LOG_DEBUG ("drop packet because signal power too Small (" <<
rxPowerW << "<" << GetEdThresholdW () << ")");
NotifyRxDrop (packet);
m_plcpSuccess = false;
goto maybeCcaBusy;
}
break;
case WifiPhy::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 (DbmToW (GetCcaMode1Threshold ()));
if (!delayUntilCcaEnd.IsZero ())
{
m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd);
}
}
void
WifiPhy::StartReceivePacket (Ptr<Packet> packet,
WifiTxVector txVector,
MpduType mpdutype,
Ptr<InterferenceHelper::Event> event)
{
NS_LOG_FUNCTION (this << packet << txVector.GetMode () << txVector.GetPreambleType () << (uint32_t)mpdutype);
NS_ASSERT (IsStateRx ());
NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
WifiMode txMode = txVector.GetMode ();
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
WifiPhy::EndReceive (Ptr<Packet> packet, WifiPreamble preamble, MpduType mpdutype, Ptr<InterferenceHelper::Event> event)
{
NS_LOG_FUNCTION (this << packet << event);
NS_ASSERT (IsStateRx ());
NS_ASSERT (event->GetEndTime () == Simulator::Now ());
InterferenceHelper::SnrPer snrPer;
snrPer = m_interference.CalculatePlcpPayloadSnrPer (event);
m_interference.NotifyRxEnd ();
if (m_plcpSuccess == true)
{
NS_LOG_DEBUG ("mode=" << (event->GetPayloadMode ().GetDataRate (event->GetTxVector ())) <<
", snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per << ", size=" << packet->GetSize ());
if (m_random->GetValue () > snrPer.per)
{
NotifyRxEnd (packet);
SignalNoiseDbm signalNoise;
signalNoise.signal = RatioToDb (event->GetRxPowerW ()) + 30;
signalNoise.noise = RatioToDb (event->GetRxPowerW () / snrPer.snr) - GetRxNoiseFigure () + 30;
MpduInfo aMpdu;
aMpdu.type = mpdutype;
aMpdu.mpduRefNumber = m_rxMpduReferenceNumber;
NotifyMonitorSniffRx (packet, (uint16_t) GetFrequency (), GetChannelNumber (), event->GetTxVector (), aMpdu, signalNoise);
m_state->SwitchFromRxEndOk (packet, snrPer.snr, event->GetTxVector ());
}
else
{
/* failure. */
NotifyRxDrop (packet);
m_state->SwitchFromRxEndError (packet, snrPer.snr);
}
}
else
{
m_state->SwitchFromRxEndError (packet, snrPer.snr);
}
if (preamble == WIFI_PREAMBLE_NONE && mpdutype == LAST_MPDU_IN_AGGREGATE)
{
m_plcpSuccess = false;
}
}
// Clause 15 rates (DSSS)
@@ -2904,32 +3401,6 @@ WifiPhy::GetMcs (uint8_t mcs) const
return m_deviceMcsSet[mcs];
}
double
WifiPhy::DbToRatio (double dB) const
{
double ratio = std::pow (10.0, dB / 10.0);
return ratio;
}
double
WifiPhy::DbmToW (double dBm) const
{
double mW = std::pow (10.0, dBm / 10.0);
return mW / 1000.0;
}
double
WifiPhy::WToDbm (double w) const
{
return 10.0 * std::log10 (w * 1000.0);
}
double
WifiPhy::RatioToDb (double ratio) const
{
return 10.0 * std::log10 (ratio);
}
bool
WifiPhy::IsStateCcaBusy (void)
{

View File

@@ -215,13 +215,62 @@ public:
* \param callback the callback to invoke
* upon successful packet reception.
*/
virtual void SetReceiveOkCallback (RxOkCallback callback) = 0;
void SetReceiveOkCallback (RxOkCallback callback);
/**
* \param callback the callback to invoke
* upon erroneous packet reception.
*/
virtual void SetReceiveErrorCallback (RxErrorCallback callback) = 0;
void SetReceiveErrorCallback (RxErrorCallback callback);
/**
* \param listener the new listener
*
* Add the input listener to the list of objects to be notified of
* PHY-level events.
*/
void RegisterListener (WifiPhyListener *listener);
/**
* \param listener the listener to be unregistered
*
* Remove the input listener from the list of objects to be notified of
* PHY-level events.
*/
void UnregisterListener (WifiPhyListener *listener);
/**
* Starting receiving the plcp of a packet (i.e. the first bit of the preamble has arrived).
*
* \param packet the arriving packet
* \param rxPowerW the receive power in W
* \param rxDuration the duration needed for the reception of the packet
*/
void StartReceivePreambleAndHeader (Ptr<Packet> packet,
double rxPowerW,
Time rxDuration);
/**
* Starting receiving the payload of a packet (i.e. the first bit of the packet has arrived).
*
* \param packet the arriving packet
* \param txVector the TXVECTOR of the arriving packet
* \param mpdutype the type of the MPDU as defined in WifiPhy::MpduType.
* \param event the corresponding event of the first time the packet arrives
*/
void StartReceivePacket (Ptr<Packet> packet,
WifiTxVector txVector,
MpduType mpdutype,
Ptr<InterferenceHelper::Event> event);
/**
* The last bit of the packet has arrived.
*
* \param packet the packet that the last bit has arrived
* \param preamble the preamble of the arriving packet
* \param mpdutype the type of the MPDU as defined in WifiPhy::MpduType.
* \param event the corresponding event of the first time the packet arrives
*/
void EndReceive (Ptr<Packet> packet, WifiPreamble preamble, MpduType mpdutype, Ptr<InterferenceHelper::Event> event);
/**
* \param packet the packet to send
* \param txVector the TXVECTOR that has tx parameters such as mode, the transmission mode to use to send
@@ -229,31 +278,25 @@ public:
* power is calculated as txPowerMin + txPowerLevel * (txPowerMax - txPowerMin) / nTxLevels
* \param mpdutype the type of the MPDU as defined in WifiPhy::MpduType.
*/
virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, MpduType mpdutype = NORMAL_MPDU) = 0;
void SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, MpduType mpdutype = NORMAL_MPDU);
/**
* \param listener the new listener
*
* Add the input listener to the list of objects to be notified of
* PHY-level events.
* \param packet the packet to send
* \param txVector the TXVECTOR that has tx parameters such as mode, the transmission mode to use to send
* this packet, and txPowerLevel, a power level to use to send this packet. The real transmission
* power is calculated as txPowerMin + txPowerLevel * (txPowerMax - txPowerMin) / nTxLevels
* \param txDuration duration of the transmission.
*/
virtual void RegisterListener (WifiPhyListener *listener) = 0;
/**
* \param listener the listener to be unregistered
*
* Remove the input listener from the list of objects to be notified of
* PHY-level events.
*/
virtual void UnregisterListener (WifiPhyListener *listener) = 0;
virtual void StartTx (Ptr<Packet> packet, WifiTxVector txVector, Time txDuration) = 0;
/**
* Put in sleep mode.
*/
virtual void SetSleepMode (void) = 0;
virtual void SetSleepMode (void);
/**
* Resume from sleep mode.
*/
virtual void ResumeFromSleep (void) = 0;
virtual void ResumeFromSleep (void);
/**
* \return true of the current state of the PHY layer is WifiPhy::IDLE, false otherwise.
@@ -1490,38 +1533,7 @@ public:
* \return a vector containing the supported channel widths, values in MHz
*/
virtual std::vector<uint32_t> GetSupportedChannelWidthSet (void) const;
/**
* Convert from dBm to Watts.
*
* \param dbm the power in dBm
*
* \return the equivalent Watts for the given dBm
*/
double DbmToW (double dbm) const;
/**
* Convert from dB to ratio.
*
* \param db
*
* \return ratio
*/
double DbToRatio (double db) const;
/**
* Convert from Watts to dBm.
*
* \param w the power in Watts
*
* \return the equivalent dBm for the given Watts
*/
double WToDbm (double w) const;
/**
* Convert from ratio to dB.
*
* \param ratio
*
* \return dB
*/
double RatioToDb (double ratio) const;
protected:
// Inherited

View File

@@ -0,0 +1,52 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016
*
* 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
*
* Author: Sébastien Deronne <sebastien.deronne@gmail.com>
*/
#include "wifi-utils.h"
#include <cmath>
namespace ns3 {
double
DbToRatio (double dB)
{
double ratio = std::pow (10.0, dB / 10.0);
return ratio;
}
double
DbmToW (double dBm)
{
double mW = std::pow (10.0, dBm / 10.0);
return mW / 1000.0;
}
double
WToDbm (double w)
{
return 10.0 * std::log10 (w * 1000.0);
}
double
RatioToDb (double ratio)
{
return 10.0 * std::log10 (ratio);
}
} //namespace ns3

View File

@@ -0,0 +1,61 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016
*
* 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
*
* Author: Sébastien Deronne <sebastien.deronne@gmail.com>
*/
#ifndef WIFI_UTILS_H
#define WIFI_UTILS_H
namespace ns3 {
/**
* Convert from dBm to Watts.
*
* \param dbm the power in dBm
*
* \return the equivalent Watts for the given dBm
*/
double DbmToW (double dbm);
/**
* Convert from dB to ratio.
*
* \param db
*
* \return ratio
*/
double DbToRatio (double db);
/**
* Convert from Watts to dBm.
*
* \param w the power in Watts
*
* \return the equivalent dBm for the given Watts
*/
double WToDbm (double w);
/**
* Convert from ratio to dB.
*
* \param ratio
*
* \return dB
*/
double RatioToDb (double ratio);
} // namespace ns3
#endif /* WIFI_UTILS_H */

View File

@@ -29,6 +29,7 @@
#include "yans-wifi-channel.h"
#include "ns3/propagation-loss-model.h"
#include "ns3/propagation-delay-model.h"
#include "wifi-utils.h"
namespace ns3 {
@@ -120,7 +121,7 @@ YansWifiChannel::Send (Ptr<YansWifiPhy> sender, Ptr<const Packet> packet, double
void
YansWifiChannel::Receive (uint32_t i, Ptr<Packet> packet, double rxPowerDbm, Time duration) const
{
m_phyList[i]->StartReceivePreambleAndHeader (packet, rxPowerDbm, duration);
m_phyList[i]->StartReceivePreambleAndHeader (packet, DbmToW (rxPowerDbm + m_phyList[i]->GetRxGain ()), duration);
}
uint32_t

View File

@@ -28,9 +28,7 @@
#include "ns3/assert.h"
#include "ns3/log.h"
#include "ns3/double.h"
#include "ampdu-tag.h"
#include "wifi-phy-tag.h"
#include <cmath>
#include "wifi-utils.h"
namespace ns3 {
@@ -66,110 +64,6 @@ YansWifiPhy::DoDispose (void)
m_channel = 0;
}
bool
YansWifiPhy::DoChannelSwitch (uint16_t nch)
{
if (!IsInitialized ())
{
//this is not channel switch, this is initialization
NS_LOG_DEBUG ("initialize to channel " << nch);
return true;
}
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 (), &WifiPhy::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 false;
switchChannel:
NS_LOG_DEBUG ("switching channel " << GetChannelNumber () << " -> " << nch);
m_state->SwitchToChannelSwitching (GetChannelSwitchDelay ());
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.
*/
return true;
}
bool
YansWifiPhy::DoFrequencySwitch (uint32_t frequency)
{
if (!IsInitialized ())
{
//this is not channel switch, this is initialization
NS_LOG_DEBUG ("start at frequency " << frequency);
return true;
}
NS_ASSERT (!IsStateSwitching ());
switch (m_state->GetState ())
{
case YansWifiPhy::RX:
NS_LOG_DEBUG ("drop packet because of channel/frequency switching while reception");
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
goto switchFrequency;
break;
case YansWifiPhy::TX:
NS_LOG_DEBUG ("channel/frequency switching postponed until end of current transmission");
Simulator::Schedule (GetDelayUntilIdle (), &WifiPhy::SetFrequency, this, frequency);
break;
case YansWifiPhy::CCA_BUSY:
case YansWifiPhy::IDLE:
goto switchFrequency;
break;
case YansWifiPhy::SLEEP:
NS_LOG_DEBUG ("frequency switching ignored in sleep mode");
break;
default:
NS_ASSERT (false);
break;
}
return false;
switchFrequency:
NS_LOG_DEBUG ("switching frequency " << GetFrequency () << " -> " << frequency);
m_state->SwitchToChannelSwitching (GetChannelSwitchDelay ());
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.
*/
return true;
}
Ptr<WifiChannel>
YansWifiPhy::GetChannel (void) const
{
@@ -184,398 +78,10 @@ YansWifiPhy::SetChannel (Ptr<YansWifiChannel> channel)
}
void
YansWifiPhy::SetSleepMode (void)
YansWifiPhy::StartTx (Ptr<Packet> packet, WifiTxVector txVector, Time txDuration)
{
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 (DbmToW (GetCcaMode1Threshold ()));
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, 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 << rxDuration);
AmpduTag ampduTag;
rxPowerDbm += GetRxGain ();
double rxPowerW = DbmToW (rxPowerDbm);
Time endRx = Simulator::Now () + rxDuration;
WifiPhyTag tag;
packet->RemovePacketTag (tag);
WifiTxVector txVector = tag.GetWifiTxVector ();
if (txVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HT
&& (txVector.GetNss () != (1 + (txVector.GetMode ().GetMcsValue () / 8))))
{
NS_FATAL_ERROR ("MCS value does not match NSS value: MCS = " << (uint16_t)txVector.GetMode ().GetMcsValue () << ", NSS = " << (uint16_t)txVector.GetNss ());
}
if (txVector.GetNss () > GetMaxSupportedRxSpatialStreams ())
{
NS_FATAL_ERROR ("Reception ends in failure because of an unsupported number of spatial streams");
}
WifiPreamble preamble = txVector.GetPreambleType ();
MpduType mpdutype = tag.GetMpduType ();
Time preambleAndHeaderDuration = CalculatePlcpPreambleAndHeaderDuration (txVector);
Ptr<InterferenceHelper::Event> event;
event = m_interference.Add (packet->GetSize (),
txVector,
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 > GetEdThresholdW ()) //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 || m_plcpSuccess == false))
{
m_plcpSuccess = false;
m_mpdusNum = 0;
NS_LOG_DEBUG ("drop packet because no PLCP preamble/header 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.GetRemainingNbOfMpdus ();
m_rxMpduReferenceNumber++;
}
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.GetRemainingNbOfMpdus () < (m_mpdusNum - 1))
{
NS_LOG_DEBUG ("Missing MPDU from the A-MPDU " << m_mpdusNum - ampduTag.GetRemainingNbOfMpdus ());
m_mpdusNum = ampduTag.GetRemainingNbOfMpdus ();
}
else
{
m_mpdusNum--;
}
}
else if (preamble != WIFI_PREAMBLE_NONE && packet->PeekPacketTag (ampduTag) && m_mpdusNum > 0)
{
NS_LOG_DEBUG ("New A-MPDU started while " << m_mpdusNum << " MPDUs from previous are lost");
m_mpdusNum = ampduTag.GetRemainingNbOfMpdus ();
}
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, mpdutype, event);
}
NS_ASSERT (m_endRxEvent.IsExpired ());
m_endRxEvent = Simulator::Schedule (rxDuration, &YansWifiPhy::EndReceive, this,
packet, preamble, mpdutype, event);
}
else
{
NS_LOG_DEBUG ("drop packet because signal power too Small (" <<
rxPowerW << "<" << GetEdThresholdW () << ")");
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 (DbmToW (GetCcaMode1Threshold ()));
if (!delayUntilCcaEnd.IsZero ())
{
m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd);
}
}
void
YansWifiPhy::StartReceivePacket (Ptr<Packet> packet,
WifiTxVector txVector,
MpduType mpdutype,
Ptr<InterferenceHelper::Event> event)
{
NS_LOG_FUNCTION (this << packet << txVector.GetMode () << txVector.GetPreambleType () << (uint32_t)mpdutype);
NS_ASSERT (IsStateRx ());
NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
WifiMode txMode = txVector.GetMode ();
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, MpduType mpdutype)
{
NS_LOG_FUNCTION (this << packet << txVector.GetMode ()
<< txVector.GetMode ().GetDataRate (txVector) << txVector.GetPreambleType ()
<< (uint32_t)txVector.GetTxPowerLevel () << (uint32_t)mpdutype);
/* 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 (txVector.GetNss () > GetMaxSupportedTxSpatialStreams ())
{
NS_FATAL_ERROR ("Unsupported number of spatial streams!");
}
if (m_state->IsStateSleep ())
{
NS_LOG_DEBUG ("Dropping packet because in sleep mode");
NotifyTxDrop (packet);
return;
}
Time txDuration = CalculateTxDuration (packet->GetSize (), txVector, GetFrequency (), mpdutype, 1);
NS_ASSERT (txDuration > NanoSeconds (0));
if (m_state->IsStateRx ())
{
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_interference.NotifyRxEnd ();
}
NotifyTxBegin (packet);
if ((mpdutype == MPDU_IN_AGGREGATE) && (txVector.GetPreambleType () != WIFI_PREAMBLE_NONE))
{
//send the first MPDU in an MPDU
m_txMpduReferenceNumber++;
}
MpduInfo aMpdu;
aMpdu.type = mpdutype;
aMpdu.mpduRefNumber = m_txMpduReferenceNumber;
NotifyMonitorSniffTx (packet, (uint16_t)GetFrequency (), GetChannelNumber (), txVector, aMpdu);
m_state->SwitchToTx (txDuration, packet, GetPowerDbm (txVector.GetTxPowerLevel ()), txVector);
Ptr<Packet> newPacket = packet->Copy (); // obtain non-const Packet
WifiPhyTag oldtag;
newPacket->RemovePacketTag (oldtag);
WifiPhyTag tag (txVector, mpdutype);
newPacket->AddPacketTag (tag);
m_channel->Send (this, newPacket, GetPowerDbm (txVector.GetTxPowerLevel ()) + GetTxGain (), txDuration);
}
void
YansWifiPhy::RegisterListener (WifiPhyListener *listener)
{
m_state->RegisterListener (listener);
}
void
YansWifiPhy::UnregisterListener (WifiPhyListener *listener)
{
m_state->UnregisterListener (listener);
}
void
YansWifiPhy::EndReceive (Ptr<Packet> packet, WifiPreamble preamble, MpduType mpdutype, Ptr<InterferenceHelper::Event> event)
{
NS_LOG_FUNCTION (this << packet << event);
NS_ASSERT (IsStateRx ());
NS_ASSERT (event->GetEndTime () == Simulator::Now ());
InterferenceHelper::SnrPer snrPer;
snrPer = m_interference.CalculatePlcpPayloadSnrPer (event);
m_interference.NotifyRxEnd ();
if (m_plcpSuccess == true)
{
NS_LOG_DEBUG ("mode=" << (event->GetPayloadMode ().GetDataRate (event->GetTxVector ())) <<
", snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per << ", size=" << packet->GetSize ());
if (m_random->GetValue () > snrPer.per)
{
NotifyRxEnd (packet);
SignalNoiseDbm signalNoise;
signalNoise.signal = RatioToDb (event->GetRxPowerW ()) + 30;
signalNoise.noise = RatioToDb (event->GetRxPowerW () / snrPer.snr) - GetRxNoiseFigure () + 30;
MpduInfo aMpdu;
aMpdu.type = mpdutype;
aMpdu.mpduRefNumber = m_rxMpduReferenceNumber;
NotifyMonitorSniffRx (packet, (uint16_t)GetFrequency (), GetChannelNumber (), event->GetTxVector (), aMpdu, signalNoise);
m_state->SwitchFromRxEndOk (packet, snrPer.snr, event->GetTxVector ());
}
else
{
/* failure. */
NotifyRxDrop (packet);
m_state->SwitchFromRxEndError (packet, snrPer.snr);
}
}
else
{
m_state->SwitchFromRxEndError (packet, snrPer.snr);
}
if (preamble == WIFI_PREAMBLE_NONE && mpdutype == LAST_MPDU_IN_AGGREGATE)
{
m_plcpSuccess = false;
}
NS_LOG_DEBUG ("Start transmission: signal power before antenna gain=" << GetPowerDbm (txVector.GetTxPowerLevel ()) << "dBm");
m_channel->Send (this, packet, GetPowerDbm (txVector.GetTxPowerLevel ()) + GetTxGain (), txDuration);
}
} //namespace ns3

View File

@@ -60,54 +60,23 @@ public:
void SetChannel (Ptr<YansWifiChannel> channel);
/**
* Starting receiving the plcp of a packet (i.e. the first bit of the preamble has arrived).
*
* \param packet the arriving packet
* \param rxPowerDbm the receive power in dBm
* \param rxDuration the duration needed for the reception of the packet
* \param packet the packet to send
* \param txVector the TXVECTOR that has tx parameters such as mode, the transmission mode to use to send
* this packet, and txPowerLevel, a power level to use to send this packet. The real transmission
* power is calculated as txPowerMin + txPowerLevel * (txPowerMax - txPowerMin) / nTxLevels
* \param txDuration duration of the transmission.
*/
void StartReceivePreambleAndHeader (Ptr<Packet> packet,
double rxPowerDbm,
Time rxDuration);
/**
* Starting receiving the payload of a packet (i.e. the first bit of the packet has arrived).
*
* \param packet the arriving packet
* \param txVector the TXVECTOR of the arriving packet
* \param mpdutype the type of the MPDU as defined in WifiPhy::MpduType.
* \param event the corresponding event of the first time the packet arrives
*/
void StartReceivePacket (Ptr<Packet> packet,
WifiTxVector txVector,
MpduType mpdutype,
Ptr<InterferenceHelper::Event> event);
void StartTx (Ptr<Packet> packet, WifiTxVector txVector, Time txDuration);
virtual void SetReceiveOkCallback (WifiPhy::RxOkCallback callback);
virtual void SetReceiveErrorCallback (WifiPhy::RxErrorCallback callback);
virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, MpduType mpdutype = NORMAL_MPDU);
virtual void RegisterListener (WifiPhyListener *listener);
virtual void UnregisterListener (WifiPhyListener *listener);
virtual void SetSleepMode (void);
virtual void ResumeFromSleep (void);
virtual Ptr<WifiChannel> GetChannel (void) const;
protected:
// Inherited
virtual void DoDispose (void);
virtual bool DoChannelSwitch (uint16_t id);
virtual bool DoFrequencySwitch (uint32_t frequency);
private:
/**
* The last bit of the packet has arrived.
*
* \param packet the packet that the last bit has arrived
* \param preamble the preamble of the arriving packet
* \param mpdutype the type of the MPDU as defined in WifiPhy::MpduType.
* \param event the corresponding event of the first time the packet arrives
*/
void EndReceive (Ptr<Packet> packet, WifiPreamble preamble, MpduType mpdutype, Ptr<InterferenceHelper::Event> event);
Ptr<YansWifiChannel> m_channel; //!< YansWifiChannel that this YansWifiPhy is connected to
};

View File

@@ -48,7 +48,8 @@ protected:
Ptr<SpectrumWifiPhy> m_phy;
Ptr<SpectrumSignalParameters> MakeSignal (double txPowerWatts);
void SendSignal (double txPowerWatts);
void SpectrumWifiPhyReceiver (bool rxSucceeded);
void SpectrumWifiPhyRxSuccess (Ptr<Packet> p, double snr, WifiTxVector txVector);
void SpectrumWifiPhyRxFailure (Ptr<Packet> p, double snr);
uint32_t m_count;
private:
virtual void DoRun (void);
@@ -104,7 +105,13 @@ SpectrumWifiPhyBasicTest::SendSignal (double txPowerWatts)
}
void
SpectrumWifiPhyBasicTest::SpectrumWifiPhyReceiver (bool rxSucceeded)
SpectrumWifiPhyBasicTest::SpectrumWifiPhyRxSuccess (Ptr<Packet> p, double snr, WifiTxVector txVector)
{
m_count++;
}
void
SpectrumWifiPhyBasicTest::SpectrumWifiPhyRxFailure (Ptr<Packet> p, double snr)
{
m_count++;
}
@@ -124,7 +131,8 @@ SpectrumWifiPhyBasicTest::DoSetup (void)
m_phy->SetErrorRateModel (error);
m_phy->SetChannelNumber (CHANNEL_NUMBER);
m_phy->SetFrequency (FREQUENCY);
m_phy->SetPacketReceivedCallback (MakeCallback (&SpectrumWifiPhyBasicTest::SpectrumWifiPhyReceiver, this));
m_phy->SetReceiveOkCallback (MakeCallback (&SpectrumWifiPhyBasicTest::SpectrumWifiPhyRxSuccess, this));
m_phy->SetReceiveErrorCallback (MakeCallback (&SpectrumWifiPhyBasicTest::SpectrumWifiPhyRxFailure, this));
//Bug 2460: CcaMode1Threshold default should be set to -62 dBm when using Spectrum
m_phy->SetCcaMode1Threshold (-62.0);
}

View File

@@ -3,6 +3,7 @@
def build(bld):
obj = bld.create_ns3_module('wifi', ['network', 'propagation', 'energy', 'spectrum', 'antenna', 'mobility'])
obj.source = [
'model/wifi-utils.cc',
'model/wifi-information-element.cc',
'model/wifi-information-element-vector.cc',
'model/wifi-channel.cc',
@@ -107,6 +108,7 @@ def build(bld):
headers = bld(features='ns3header')
headers.module = 'wifi'
headers.source = [
'model/wifi-utils.h',
'model/wifi-information-element.h',
'model/wifi-information-element-vector.h',
'model/wifi-net-device.h',