wifi: Add threshold-based preamble detection model

This commit is contained in:
Sébastien Deronne
2018-12-03 21:18:05 +01:00
parent b3e470c64f
commit 2bd74fdbd7
26 changed files with 669 additions and 60 deletions

View File

@@ -58,6 +58,7 @@ us a note on ns-developers mailing list.</p>
</li>
<li>A new attribute <b>WifiPhy::PostReceptionErrorModel</b> has been added to force specific packet drops.
</li>
<li>A new attribute <b>WifiPhy::PreambleDetectionModel</b> has been added to decide whether PHY preambles are successfully detected.
</li>
<li>New attributes <b>QosTxop::AddBaResponseTimeout</b> and <b>QosTxop::FailedAddBaTimeout</b> have been added to set the timeout to wait for an ADDBA response after the ACK to the ADDBA request is received and to set the timeout after a failed BA agreement, respectively.
</li>

View File

@@ -23,6 +23,7 @@ requirements (Note: not all features available on all platforms):
New user-visible features
-------------------------
- (wifi) Preamble detection can now be modelled
Bugs fixed
----------

View File

@@ -175,7 +175,6 @@ The following details pertain to the physical layer and channel models:
* 802.11 PCF implementation currently assumes a DTIM interval equal to the beacon interval
* Authentication and encryption are missing
* Processing delays are not modeled
* PLCP preamble reception is not modeled
* PHY_RXSTART is not supported
* The current implementation assumes that secondary channels are always higher than primary channels
* Cases where RTS/CTS and ACK are transmitted using HT/VHT/HE formats are not supported
@@ -297,9 +296,9 @@ In the standard, there is also what is called the "minimum modulation
and coding rate sensitivity" in section 18.3.10.6 CCA requirements.
This is analogous to the RxSensitivity attribute in ``YansWifiPhy``.
CCA busy state is not raised in this model when this threshold is exceeded
but instead RX state is immediately reached, since it is assumed that PLCP
sync always succeeds in this model. Even if the PLCP header reception fails, the
channel state is still held in RX until YansWifiPhy::EndReceive().
but instead RX state is immediately reachedif PHY preamble detection is successful.
Even if the PHY header reception fails, the channel state is still held
in RX until YansWifiPhy::EndReceive().
In ns-3, the values of these attributes are -101 dBm for RxSensitivity
and -62 dBm for CcaEdThreshold.
@@ -311,10 +310,15 @@ calculated from the transmission power and adjusted based on the Tx gain
of the transmitter, Rx gain of the receiver, and any path loss propagation
model in effect.
The packet reception occurs in two stages. First, an event is scheduled
for when the PLCP header has been received. PLCP header is often transmitted
The packet reception occurs in three stages. First, an event is scheduled
for when PHY preamble has been detected. This decides whether the preamble
can be detected, by calling a preamble detection model. In case there is no
preamble detection model attached to the PHY, it assumes preamble is always detected.
Currently, there is only a simple threshold-based preamble detection model in ns-3,
called ``ThresholdPreambleDetectionModel``. If PHY preamble has been successfully detected,
it schedules a second event for when PHY header has been received. PHY header is often transmitted
at a lower modulation rate than is the payload. The portion of the packet
corresponding to the PLCP header is evaluated for probability of error
corresponding to the PHY header is evaluated for probability of error
based on the observed SNR. The InterferenceHelper object returns a value
for "probability of error (PER)" for this header based on the SNR that has
been tracked by the InterferenceHelper. The ``YansWifiPhy`` then draws

View File

@@ -25,6 +25,7 @@
#include "interference-helper.h"
#include "wifi-phy.h"
#include "error-rate-model.h"
#include "wifi-utils.h"
namespace ns3 {
@@ -229,26 +230,36 @@ InterferenceHelper::CalculateSnr (double signal, double noiseInterference, uint1
double noiseFloor = m_noiseFigure * Nt;
double noise = noiseFloor + noiseInterference;
double snr = signal / noise; //linear scale
NS_LOG_DEBUG ("bandwidth(MHz)=" << channelWidth << ", signal(W)= " << signal << ", noise(W)=" << noiseFloor << ", interference(W)=" << noiseInterference << ", snr(linear)=" << snr);
NS_LOG_DEBUG ("bandwidth(MHz)=" << channelWidth << ", signal(W)= " << signal << ", noise(W)=" << noiseFloor << ", interference(W)=" << noiseInterference << ", snr=" << RatioToDb(snr) << "dB");
return snr;
}
double
InterferenceHelper::CalculateNoiseInterferenceW (Ptr<Event> event, NiChanges *ni) const
{
double noiseInterference = m_firstPower;
double noiseInterferenceW = m_firstPower;
auto it = m_niChanges.find (event->GetStartTime ());
for (; it != m_niChanges.end () && it->second.GetEvent () != event; ++it)
for (; it != m_niChanges.end (); ++it)
{
noiseInterference = it->second.GetPower ();
if (it->second.GetEvent () == event)
{
continue;
}
if (it->first > Simulator::Now ())
{
break;
}
noiseInterferenceW = it->second.GetPower () - event->GetRxPowerW ();
}
it = m_niChanges.find (event->GetStartTime ());
for (; it != m_niChanges.end () && it->second.GetEvent () != event; ++it);
ni->emplace (event->GetStartTime (), NiChange (0, event));
while (++it != m_niChanges.end () && it->second.GetEvent () != event)
{
ni->insert (*it);
}
ni->emplace (event->GetEndTime (), NiChange (0, event));
return noiseInterference;
return noiseInterferenceW;
}
double

View File

@@ -0,0 +1,36 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2018 University of Washington
*
* 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 "preamble-detection-model.h"
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (PreambleDetectionModel);
TypeId PreambleDetectionModel::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::PreambleDetectionModel")
.SetParent<Object> ()
.SetGroupName ("Wifi")
;
return tid;
}
} //namespace ns3

View File

@@ -0,0 +1,58 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2018 University of Washington
*
* 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 PREAMBLE_DETECTION_MODEL_H
#define PREAMBLE_DETECTION_MODEL_H
#include "ns3/object.h"
namespace ns3 {
/**
* \ingroup wifi
* \brief the interface for Wifi's preamble detection models
*
*/
class PreambleDetectionModel : public Object
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
/**
* A pure virtual method that must be implemented in the subclass.
* This method returns whether the preamble detection was successful.
*
* \param snr the SNR of the received signal.
* \param channelWidth the channel width of the received signal in MHz.
*
* \return true if the preamble has been detected,
* false otherwise
*/
virtual bool IsPreambleDetected (double snr, double channelWidth) const = 0;
};
} //namespace ns3
#endif /* PREAMBLE_DETECTION_MODEL_H */

View File

@@ -240,7 +240,7 @@ SpectrumWifiPhy::StartRx (Ptr<SpectrumSignalParameters> rxParams)
NS_LOG_INFO ("Received Wi-Fi signal");
Ptr<Packet> packet = wifiRxParams->packet->Copy ();
StartReceivePreambleAndHeader (packet, rxPowerW, rxDuration);
StartReceivePreamble (packet, rxPowerW, rxDuration);
}
Ptr<AntennaModel>

View File

@@ -0,0 +1,65 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2018 University of Washington
*
* 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 "ns3/log.h"
#include "ns3/double.h"
#include "threshold-preamble-detection-model.h"
#include "wifi-utils.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("ThresholdPreambleDetectionModel");
NS_OBJECT_ENSURE_REGISTERED (ThresholdPreambleDetectionModel);
TypeId
ThresholdPreambleDetectionModel::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::ThresholdPreambleDetectionModel")
.SetParent<PreambleDetectionModel> ()
.SetGroupName ("Wifi")
.AddConstructor<ThresholdPreambleDetectionModel> ()
.AddAttribute ("Threshold",
"Preamble is successfully detection if the SNR is at or above this value (expressed in dB).",
DoubleValue (2),
MakeDoubleAccessor (&ThresholdPreambleDetectionModel::m_threshold),
MakeDoubleChecker<double> ())
;
return tid;
}
ThresholdPreambleDetectionModel::ThresholdPreambleDetectionModel ()
{
NS_LOG_FUNCTION (this);
}
ThresholdPreambleDetectionModel::~ThresholdPreambleDetectionModel ()
{
NS_LOG_FUNCTION (this);
}
bool
ThresholdPreambleDetectionModel::IsPreambleDetected (double snr, double channelWidth) const
{
NS_LOG_FUNCTION (this);
return (RatioToDb (snr) >= m_threshold);
}
} //namespace ns3

View File

@@ -0,0 +1,63 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2018 University of Washington
*
* 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 THRESHOLD_PREAMBLE_DETECTION_MODEL_H
#define THRESHOLD_PREAMBLE_DETECTION_MODEL_H
#include "preamble-detection-model.h"
namespace ns3 {
/**
* \ingroup wifi
*
* A threshold-based model for detecting PHY preamble.
* This model assumes that a preamble is successfully detected if SNR is at or above a given threshold. By default, this threshold is set to 2 dB.
*/
class ThresholdPreambleDetectionModel : public PreambleDetectionModel
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
ThresholdPreambleDetectionModel ();
~ThresholdPreambleDetectionModel ();
/**
* This method returns whether the preamble detection was successful.
*
* \param snr the SNR ratio (not dB) of the received signal.
* \param channelWidth the channel width of the received signal in MHz.
*
* \return true if the preamble has been detected,
* false otherwise
*/
bool IsPreambleDetected (double snr, double channelWidth) const;
private:
double m_threshold; ///< SNR threshold in dB used to decide whether a preamble is successfully received
};
} //namespace ns3
#endif /* THRESHOLD_PREAMBLE_DETECTION_MODEL_H */

View File

@@ -30,6 +30,7 @@
#include "ampdu-tag.h"
#include "wifi-utils.h"
#include "frame-capture-model.h"
#include "preamble-detection-model.h"
#include "wifi-radio-energy-model.h"
#include "error-rate-model.h"
#include "wifi-net-device.h"
@@ -308,6 +309,11 @@ WifiPhy::GetTypeId (void)
PointerValue (),
MakePointerAccessor (&WifiPhy::m_frameCaptureModel),
MakePointerChecker <FrameCaptureModel> ())
.AddAttribute ("PreambleDetectionModel",
"Ptr to an object that implements the preamble detection model",
PointerValue (),
MakePointerAccessor (&WifiPhy::m_preambleDetectionModel),
MakePointerChecker <PreambleDetectionModel> ())
.AddAttribute ("PostReceptionErrorModel",
"An optional packet error model can be added to the receive "
"packet process after any propagation-based (SNR-based) error "
@@ -372,6 +378,7 @@ WifiPhy::WifiPhy ()
m_rxMpduReferenceNumber (0xffffffff),
m_endRxEvent (),
m_endPlcpRxEvent (),
m_endPreambleDetectionEvent (),
m_standard (WIFI_PHY_STANDARD_UNSPECIFIED),
m_isConstructed (false),
m_channelCenterFrequency (0),
@@ -401,6 +408,9 @@ void
WifiPhy::DoDispose (void)
{
NS_LOG_FUNCTION (this);
m_endRxEvent.Cancel ();
m_endPlcpRxEvent.Cancel ();
m_endPreambleDetectionEvent.Cancel ();
m_device = 0;
m_mobility = 0;
m_state = 0;
@@ -762,6 +772,12 @@ WifiPhy::SetFrameCaptureModel (const Ptr<FrameCaptureModel> model)
m_frameCaptureModel = model;
}
void
WifiPhy::SetPreambleDetectionModel (const Ptr<PreambleDetectionModel> model)
{
m_preambleDetectionModel = model;
}
void
WifiPhy::SetWifiRadioEnergyModel (const Ptr<WifiRadioEnergyModel> wifiRadioEnergyModel)
{
@@ -1506,6 +1522,7 @@ WifiPhy::DoChannelSwitch (uint8_t nch)
NS_LOG_DEBUG ("drop packet because of channel switching while reception");
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_endPreambleDetectionEvent.Cancel ();
goto switchChannel;
break;
case WifiPhyState::TX:
@@ -1514,6 +1531,11 @@ WifiPhy::DoChannelSwitch (uint8_t nch)
break;
case WifiPhyState::CCA_BUSY:
case WifiPhyState::IDLE:
if (m_endPreambleDetectionEvent.IsRunning ())
{
m_endPreambleDetectionEvent.Cancel ();
m_endRxEvent.Cancel ();
}
goto switchChannel;
break;
case WifiPhyState::SLEEP:
@@ -1558,6 +1580,7 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency)
NS_LOG_DEBUG ("drop packet because of channel/frequency switching while reception");
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_endPreambleDetectionEvent.Cancel ();
goto switchFrequency;
break;
case WifiPhyState::TX:
@@ -1566,6 +1589,11 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency)
break;
case WifiPhyState::CCA_BUSY:
case WifiPhyState::IDLE:
if (m_endPreambleDetectionEvent.IsRunning ())
{
m_endPreambleDetectionEvent.Cancel ();
m_endRxEvent.Cancel ();
}
goto switchFrequency;
break;
case WifiPhyState::SLEEP:
@@ -1629,22 +1657,10 @@ void
WifiPhy::SetOffMode (void)
{
NS_LOG_FUNCTION (this);
switch (m_state->GetState ())
{
case WifiPhyState::RX:
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
case WifiPhyState::TX:
case WifiPhyState::SWITCHING:
case WifiPhyState::CCA_BUSY:
case WifiPhyState::IDLE:
case WifiPhyState::SLEEP:
m_state->SwitchToOff ();
break;
default:
NS_ASSERT (false);
break;
}
m_endPlcpRxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_endPreambleDetectionEvent.Cancel ();
m_state->SwitchToOff ();
}
void
@@ -1726,6 +1742,12 @@ WifiPhy::GetHePlcpHeaderMode ()
return WifiPhy::GetHeMcs0 ();
}
Time
WifiPhy::GetPreambleDetectionDuration (void)
{
return MicroSeconds (4);
}
Time
WifiPhy::GetPlcpTrainingSymbolDuration (WifiTxVector txVector)
{
@@ -2389,12 +2411,23 @@ WifiPhy::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, MpduType m
Time txDuration = CalculateTxDuration (packet->GetSize (), txVector, GetFrequency (), mpdutype, 1);
NS_ASSERT (txDuration.IsStrictlyPositive ());
if (m_state->IsStateRx ())
if (m_endPreambleDetectionEvent.IsRunning ())
{
m_endPreambleDetectionEvent.Cancel ();
}
if (m_endPlcpRxEvent.IsRunning ())
{
m_endPlcpRxEvent.Cancel ();
}
if (m_endRxEvent.IsRunning ())
{
m_endRxEvent.Cancel ();
}
if (m_state->IsStateRx ())
{
m_interference.NotifyRxEnd ();
}
NotifyTxBegin (packet);
if ((mpdutype == MPDU_IN_AGGREGATE) && (txVector.GetPreambleType () != WIFI_PREAMBLE_NONE))
{
@@ -2427,7 +2460,39 @@ WifiPhy::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, MpduType m
}
void
WifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerW, Time rxDuration)
WifiPhy::StartReceiveHeader (Ptr<Packet> packet, WifiTxVector txVector, MpduType mpdutype, Ptr<Event> event, Time rxDuration)
{
NS_LOG_FUNCTION (this << packet << txVector.GetMode () << txVector.GetPreambleType () << +mpdutype);
NS_ASSERT (!IsStateRx ());
NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
InterferenceHelper::SnrPer snrPer = m_interference.CalculatePlcpHeaderSnrPer (event);
double snr = snrPer.snr;
NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per);
if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (snr, m_channelWidth)))
{
m_state->SwitchToRx (rxDuration);
NotifyRxBegin (packet);
Time remainingPreambleHeaderDuration = CalculatePlcpPreambleAndHeaderDuration (txVector) - GetPreambleDetectionDuration ();
m_endPlcpRxEvent = Simulator::Schedule (remainingPreambleHeaderDuration, &WifiPhy::StartReceivePacket, this,
packet, txVector, mpdutype, event);
NS_ASSERT (m_endRxEvent.IsExpired ());
m_endRxEvent = Simulator::Schedule (rxDuration, &WifiPhy::EndReceive, this,
packet, txVector.GetPreambleType (), mpdutype, event);
}
else
{
NS_LOG_DEBUG ("Packet reception could not be started because PHY preamble detection failed");
m_plcpSuccess = false;
m_interference.NotifyRxEnd ();
}
}
void
WifiPhy::StartReceivePreamble (Ptr<Packet> packet, double rxPowerW, Time rxDuration)
{
WifiPhyTag tag;
bool found = packet->RemovePacketTag (tag);
@@ -2456,8 +2521,7 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerW, Tim
if (tag.GetFrameComplete () == 0)
{
NS_LOG_DEBUG ("drop packet because of incomplete frame");
NotifyRxDrop (packet);
NS_LOG_DEBUG ("Packet reception stopped because transmitter has been switched off");
m_plcpSuccess = false;
return;
}
@@ -2471,8 +2535,7 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerW, Tim
Time endRx = Simulator::Now () + rxDuration;
if (txVector.GetNss () > GetMaxSupportedRxSpatialStreams ())
{
NS_LOG_DEBUG ("drop packet because not enough RX antennas");
NotifyRxDrop (packet);
NS_LOG_DEBUG ("Packet reception could not be started because not enough RX antennas");
m_plcpSuccess = false;
if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ())
{
@@ -2585,8 +2648,6 @@ WifiPhy::StartReceivePacket (Ptr<Packet> packet,
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))
@@ -2603,7 +2664,7 @@ WifiPhy::StartReceivePacket (Ptr<Packet> packet,
}
else //plcp reception failed
{
NS_LOG_DEBUG ("drop packet because plcp preamble/header reception failed");
NS_LOG_DEBUG ("drop packet because PHY header reception failed");
NotifyRxDrop (packet);
m_plcpSuccess = false;
}
@@ -3679,6 +3740,10 @@ void
WifiPhy::AbortCurrentReception ()
{
NS_LOG_FUNCTION (this);
if (m_endPreambleDetectionEvent.IsRunning ())
{
m_endPreambleDetectionEvent.Cancel ();
}
if (m_endPlcpRxEvent.IsRunning ())
{
m_endPlcpRxEvent.Cancel ();
@@ -3741,22 +3806,31 @@ WifiPhy::StartRx (Ptr<Packet> packet, WifiTxVector txVector, MpduType mpdutype,
NS_LOG_DEBUG ("sync to signal (power=" << rxPowerW << "W)");
m_currentEvent = event;
m_state->SwitchToRx (rxDuration);
NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
NotifyRxBegin (packet);
m_interference.NotifyRxStart ();
if (preamble != WIFI_PREAMBLE_NONE)
m_interference.NotifyRxStart (); //We need to notify it now so that it starts recording events
if (preamble == WIFI_PREAMBLE_NONE)
{
NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
Time preambleAndHeaderDuration = CalculatePlcpPreambleAndHeaderDuration (txVector);
m_endPlcpRxEvent = Simulator::Schedule (preambleAndHeaderDuration, &WifiPhy::StartReceivePacket, this,
packet, txVector, mpdutype, event);
}
m_state->SwitchToRx (rxDuration);
NotifyRxBegin (packet);
m_interference.NotifyRxStart ();
NS_ASSERT (m_endRxEvent.IsExpired ());
m_endRxEvent = Simulator::Schedule (rxDuration, &WifiPhy::EndReceive, this,
packet, preamble, mpdutype, event);
NS_ASSERT (m_endRxEvent.IsExpired ());
m_endRxEvent = Simulator::Schedule (rxDuration, &WifiPhy::EndReceive, this,
packet, txVector.GetPreambleType (), mpdutype, event);
}
else
{
if (!m_endPreambleDetectionEvent.IsRunning ())
{
Time startOfPreambleDuration = GetPreambleDetectionDuration ();
Time remainingRxDuration = rxDuration - startOfPreambleDuration;
m_endPreambleDetectionEvent = Simulator::Schedule (startOfPreambleDuration, &WifiPhy::StartReceiveHeader, this,
packet, txVector, mpdutype, event, remainingRxDuration);
}
else
{
NS_LOG_DEBUG ("Ignore packet because RX is already decoding preamble");
}
}
}
int64_t

View File

@@ -41,6 +41,7 @@ class NetDevice;
class MobilityModel;
class WifiPhyStateHelper;
class FrameCaptureModel;
class PreambleDetectionModel;
class WifiRadioEnergyModel;
class UniformRandomVariable;
@@ -114,15 +115,29 @@ public:
void SetCapabilitiesChangedCallback (Callback<void> callback);
/**
* Starting receiving the plcp of a packet (i.e. the first bit of the preamble has arrived).
* Starting receiving the PHY preamble 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);
void StartReceivePreamble (Ptr<Packet> packet,
double rxPowerW,
Time rxDuration);
/**
* Starting receiving the PHY header of a packet (i.e. after the end of receiving the preamble).
*
* \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 StartReceiveHeader (Ptr<Packet> packet,
WifiTxVector txVector,
MpduType mpdutype,
Ptr<Event> event,
Time rxDuration);
/**
* Starting receiving the payload of a packet (i.e. the first bit of the packet has arrived).
@@ -252,6 +267,12 @@ public:
*/
static Time CalculatePlcpPreambleAndHeaderDuration (WifiTxVector txVector);
/**
*
* \return the preamble detection duration, which is the time correletion needs to detect the start of an incoming frame.
*/
Time GetPreambleDetectionDuration (void);
/**
* \param txVector the transmission parameters used for this packet
*
@@ -1446,6 +1467,12 @@ public:
* \param frameCaptureModel the frame capture model
*/
void SetFrameCaptureModel (const Ptr<FrameCaptureModel> frameCaptureModel);
/**
* Sets the preamble detection model.
*
* \param preambleDetectionModel the preamble detection model
*/
void SetPreambleDetectionModel (const Ptr<PreambleDetectionModel> preambleDetectionModel);
/**
* Sets the wifi radio energy model.
*
@@ -1524,8 +1551,9 @@ protected:
uint32_t m_txMpduReferenceNumber; //!< A-MPDU reference number to identify all transmitted subframes belonging to the same received A-MPDU
uint32_t m_rxMpduReferenceNumber; //!< A-MPDU reference number to identify all received subframes belonging to the same received A-MPDU
EventId m_endRxEvent; //!< the end reeive event
EventId m_endPlcpRxEvent; //!< the end PLCP receive event
EventId m_endRxEvent; //!< the end of receive event
EventId m_endPlcpRxEvent; //!< the end of PLCP receive event
EventId m_endPreambleDetectionEvent; //!< the end of preamble detection event
private:
/**
@@ -1807,6 +1835,7 @@ private:
Ptr<Event> m_currentEvent; //!< Hold the current event
Ptr<FrameCaptureModel> m_frameCaptureModel; //!< Frame capture model
Ptr<PreambleDetectionModel> m_preambleDetectionModel; //!< Preamble detection model
Ptr<WifiRadioEnergyModel> m_wifiRadioEnergyModel; //!< Wifi radio energy model
Ptr<ErrorModel> m_postReceptionErrorModel; //!< Error model for receive packet events

View File

@@ -132,7 +132,7 @@ YansWifiChannel::Receive (Ptr<YansWifiPhy> phy, Ptr<Packet> packet, double rxPow
NS_LOG_INFO ("Received signal too weak to process: " << rxPowerDbm << " dBm");
return;
}
phy->StartReceivePreambleAndHeader (packet, DbmToW (rxPowerDbm + phy->GetRxGain ()), duration);
phy->StartReceivePreamble (packet, DbmToW (rxPowerDbm + phy->GetRxGain ()), duration);
}
std::size_t

View File

@@ -0,0 +1,254 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2018 University of Washington
*
* 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 "ns3/log.h"
#include "ns3/test.h"
#include "ns3/pointer.h"
#include "ns3/spectrum-wifi-helper.h"
#include "ns3/wifi-spectrum-value-helper.h"
#include "ns3/spectrum-wifi-phy.h"
#include "ns3/nist-error-rate-model.h"
#include "ns3/wifi-mac-header.h"
#include "ns3/wifi-mac-trailer.h"
#include "ns3/wifi-phy-tag.h"
#include "ns3/wifi-spectrum-signal-parameters.h"
#include "ns3/wifi-utils.h"
#include "ns3/threshold-preamble-detection-model.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("TestThresholdPreambleDetectionWithoutFrameCapture");
static const uint8_t CHANNEL_NUMBER = 36;
static const uint32_t FREQUENCY = 5180; // MHz
static const uint16_t CHANNEL_WIDTH = 20; // MHz
static const uint16_t GUARD_WIDTH = CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
/**
* \ingroup wifi-test
* \ingroup tests
*
* \brief Wifi Preamble Detection Test
*/
class TestThresholdPreambleDetectionWithoutFrameCapture : public TestCase
{
public:
TestThresholdPreambleDetectionWithoutFrameCapture ();
virtual ~TestThresholdPreambleDetectionWithoutFrameCapture ();
protected:
virtual void DoSetup (void);
Ptr<SpectrumWifiPhy> m_phy; ///< Phy
/**
* Send packet function
* \param txPowerDbm the transmit power in dBm
*/
void SendPacket (double txPowerDbm);
/**
* Spectrum wifi receive success function
* \param p the packet
* \param snr the SNR
* \param txVector the transmit vector
*/
void SpectrumWifiPhyRxSuccess (Ptr<Packet> p, double snr, WifiTxVector txVector);
/**
* Spectrum wifi receive failure function
*/
void SpectrumWifiPhyRxFailure (void);
uint32_t m_countRxSuccess; ///< count RX success
uint32_t m_countRxFailure; ///< count RX failure
private:
virtual void DoRun (void);
/**
* Check the PHY state
* \param expectedState the expected PHY state
*/
void CheckPhyState (WifiPhyState expectedState);
/**
* Check the number of received packets
* \param expectedSuccessCount the number of successfully received packets
* \param expectedFailureCount the number of unsuccessfully received packets
*/
void CheckRxPacketCount (uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
};
TestThresholdPreambleDetectionWithoutFrameCapture::TestThresholdPreambleDetectionWithoutFrameCapture ()
: TestCase ("Threshold preamble detection model test when no frame capture model is applied"),
m_countRxSuccess (0),
m_countRxFailure (0)
{
}
void
TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket (double txPowerDbm)
{
WifiTxVector txVector = WifiTxVector (WifiPhy::GetHeMcs11 (), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false, false);
MpduType mpdutype = NORMAL_MPDU;
Ptr<Packet> pkt = Create<Packet> (1000);
WifiMacHeader hdr;
WifiMacTrailer trailer;
hdr.SetType (WIFI_MAC_QOSDATA);
hdr.SetQosTid (0);
uint32_t size = pkt->GetSize () + hdr.GetSize () + trailer.GetSerializedSize ();
Time txDuration = m_phy->CalculateTxDuration (size, txVector, m_phy->GetFrequency (), mpdutype, 0);
hdr.SetDuration (txDuration);
pkt->AddHeader (hdr);
pkt->AddTrailer (trailer);
WifiPhyTag tag (txVector, mpdutype, 1);
pkt->AddPacketTag (tag);
Ptr<SpectrumValue> txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (txPowerDbm), GUARD_WIDTH);
Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters> ();
txParams->psd = txPowerSpectrum;
txParams->txPhy = 0;
txParams->duration = txDuration;
txParams->packet = pkt;
m_phy->StartRx (txParams);
}
void
TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState (WifiPhyState expectedState)
{
WifiPhyState currentState;
PointerValue ptr;
m_phy->GetAttribute ("State", ptr);
Ptr <WifiPhyStateHelper> state = DynamicCast <WifiPhyStateHelper> (ptr.Get<WifiPhyStateHelper> ());
currentState = state->GetState ();
NS_TEST_ASSERT_MSG_EQ (currentState, expectedState, "PHY State " << currentState << " does not match expected state " << expectedState << " at " << Simulator::Now ());
}
void
TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount (uint32_t expectedSuccessCount, uint32_t expectedFailureCount)
{
NS_TEST_ASSERT_MSG_EQ (m_countRxSuccess, expectedSuccessCount, "Didn't receive right number of successful packets");
NS_TEST_ASSERT_MSG_EQ (m_countRxFailure, expectedFailureCount, "Didn't receive right number of unsuccessful packets");
}
void
TestThresholdPreambleDetectionWithoutFrameCapture::SpectrumWifiPhyRxSuccess (Ptr<Packet> p, double snr, WifiTxVector txVector)
{
NS_LOG_FUNCTION (this << p << snr << txVector);
m_countRxSuccess++;
}
void
TestThresholdPreambleDetectionWithoutFrameCapture::SpectrumWifiPhyRxFailure (void)
{
NS_LOG_FUNCTION (this);
m_countRxFailure++;
}
TestThresholdPreambleDetectionWithoutFrameCapture::~TestThresholdPreambleDetectionWithoutFrameCapture ()
{
}
void
TestThresholdPreambleDetectionWithoutFrameCapture::DoSetup (void)
{
m_phy = CreateObject<SpectrumWifiPhy> ();
m_phy->ConfigureStandard (WIFI_PHY_STANDARD_80211ax_5GHZ);
Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel> ();
m_phy->SetErrorRateModel (error);
m_phy->SetChannelNumber (CHANNEL_NUMBER);
m_phy->SetFrequency (FREQUENCY);
m_phy->SetReceiveOkCallback (MakeCallback (&TestThresholdPreambleDetectionWithoutFrameCapture::SpectrumWifiPhyRxSuccess, this));
m_phy->SetReceiveErrorCallback (MakeCallback (&TestThresholdPreambleDetectionWithoutFrameCapture::SpectrumWifiPhyRxFailure, this));
Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel> ();
m_phy->SetPreambleDetectionModel (preambleDetectionModel);
}
// Test that the expected number of packet receptions occur.
void
TestThresholdPreambleDetectionWithoutFrameCapture::DoRun (void)
{
double txPowerDbm = -30;
//CASE 1: send one packet and check PHY state: packet reception should succeed
Simulator::Schedule (Seconds (1.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
// At 4us, STA PHY STATE should be IDLE
Simulator::Schedule (Seconds (1.0) + MicroSeconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
// At 5us, STA PHY STATE should be RX
Simulator::Schedule (Seconds (1.0) + MicroSeconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::RX);
// Packet should have been successfully received
Simulator::Schedule (Seconds (1.1), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount, this, 1, 0);
//CASE 2: send two packets with same power within the 4us window and check PHY state: PHY preamble detection should fail
Simulator::Schedule (Seconds (2.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
Simulator::Schedule (Seconds (2.0) + MicroSeconds (2.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
Simulator::Schedule (Seconds (2.0) + MicroSeconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
Simulator::Schedule (Seconds (2.0) + MicroSeconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
// No more packet should have been successfully received, and since preamble detection did not pass the packet should not have been counted as a failure
Simulator::Schedule (Seconds (2.1), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount, this, 1, 0);
//CASE 3: send two packets with second one 3 dB weaker within the 4us window and check PHY state: PHY preamble detection should succeed and packet reception should fail
Simulator::Schedule (Seconds (3.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
Simulator::Schedule (Seconds (3.0) + MicroSeconds (2.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm - 3);
Simulator::Schedule (Seconds (3.0) + MicroSeconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
Simulator::Schedule (Seconds (3.0) + MicroSeconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::RX);
// In this case, the first packet should be marked as a failure
Simulator::Schedule (Seconds (3.1), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount, this, 1, 1);
//CASE 4: send two packets with second one 3 dB higher within the 4us window and check PHY state: PHY preamble detection should fail and no packets should enter the reception stage
Simulator::Schedule (Seconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
Simulator::Schedule (Seconds (4.0) + MicroSeconds (2.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm + 3);
Simulator::Schedule (Seconds (4.0) + MicroSeconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
Simulator::Schedule (Seconds (4.0) + MicroSeconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
Simulator::Schedule (Seconds (4.1), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount, this, 1, 1);
//CASE 5: idem but send the second packet after the 4us window: PHY preamble detection should succeed and packet reception should fail
Simulator::Schedule (Seconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm);
Simulator::Schedule (Seconds (5.0) + MicroSeconds (6.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, txPowerDbm + 3);
Simulator::Schedule (Seconds (5.0) + MicroSeconds (4.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
Simulator::Schedule (Seconds (5.0) + MicroSeconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::RX);
Simulator::Schedule (Seconds (5.1), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckRxPacketCount, this, 1, 2);
Simulator::Run ();
Simulator::Destroy ();
}
/**
* \ingroup wifi-test
* \ingroup tests
*
* \brief Preamble Detection Test Suite
*/
class PreambleDetectionTestSuite : public TestSuite
{
public:
PreambleDetectionTestSuite ();
};
PreambleDetectionTestSuite::PreambleDetectionTestSuite ()
: TestSuite ("wifi-preamble-detection", UNIT)
{
AddTestCase (new TestThresholdPreambleDetectionWithoutFrameCapture, TestCase::QUICK);
}
static PreambleDetectionTestSuite preambleDetectionTestSuite; ///< the test suite

View File

@@ -1025,7 +1025,6 @@ SetChannelFrequencyTest::DoRun ()
}
Simulator::Destroy ();
}
//-----------------------------------------------------------------------------
@@ -1656,6 +1655,9 @@ void
StaWifiMacScanningTestCase::DoRun (void)
{
{
RngSeedManager::SetSeed (1);
RngSeedManager::SetRun (1);
NodeContainer nodes = Setup (false, false);
Ptr<Node> nearestAp = nodes.Get (2);
Mac48Address nearestApAddr = DynamicCast<WifiNetDevice> (nearestAp->GetDevice (0))->GetMac ()->GetAddress ();
@@ -1670,6 +1672,9 @@ StaWifiMacScanningTestCase::DoRun (void)
}
m_associatedApBssid = Mac48Address ();
{
RngSeedManager::SetSeed (1);
RngSeedManager::SetRun (1);
NodeContainer nodes = Setup (true, true);
Ptr<Node> nearestAp = nodes.Get (2);
Mac48Address nearestApAddr = DynamicCast<WifiNetDevice> (nearestAp->GetDevice (0))->GetMac ()->GetAddress ();
@@ -1682,6 +1687,9 @@ StaWifiMacScanningTestCase::DoRun (void)
}
m_associatedApBssid = Mac48Address ();
{
RngSeedManager::SetSeed (1);
RngSeedManager::SetRun (1);
NodeContainer nodes = Setup (true, false);
Ptr<Node> nearestAp = nodes.Get (2);
Mac48Address secondNearestApAddr = DynamicCast<WifiNetDevice> (nodes.Get (1)->GetDevice (0))->GetMac ()->GetAddress ();

View File

@@ -85,6 +85,8 @@ def build(bld):
'model/he-capabilities.cc',
'model/frame-capture-model.cc',
'model/simple-frame-capture-model.cc',
'model/preamble-detection-model.cc',
'model/threshold-preamble-detection-model.cc',
'model/he-operation.cc',
'model/he-configuration.cc',
'model/extended-capabilities.cc',
@@ -112,6 +114,7 @@ def build(bld):
'test/wifi-error-rate-models-test.cc',
'test/wifi-transmit-mask-test.cc',
'test/wifi-phy-thresholds-test.cc',
'test/preamble-detection-test.cc',
]
headers = bld(features='ns3header')
@@ -200,6 +203,8 @@ def build(bld):
'model/he-capabilities.h',
'model/frame-capture-model.h',
'model/simple-frame-capture-model.h',
'model/preamble-detection-model.h',
'model/threshold-preamble-detection-model.h',
'model/qos-blocked-destinations.h',
'model/he-operation.h',
'model/he-configuration.h',