wifi: (fixes #2552) Remove remaining code duplication between Yans and Spectrum
This commit is contained in:
@@ -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
|
||||
------------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
52
src/wifi/model/wifi-utils.cc
Normal file
52
src/wifi/model/wifi-utils.cc
Normal 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
|
||||
61
src/wifi/model/wifi-utils.h
Normal file
61
src/wifi/model/wifi-utils.h
Normal 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 */
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user