wifi: Add frame capture support

This commit is contained in:
Sébastien Deronne
2017-05-06 18:00:21 +02:00
parent d54ab3eda0
commit 5bcbf9067c
13 changed files with 647 additions and 113 deletions

View File

@@ -55,9 +55,17 @@
#include "ns3/propagation-delay-model.h"
#include "ns3/nist-error-rate-model.h"
#include "ns3/constant-position-mobility-model.h"
#include "ns3/simple-frame-capture-model.h"
#include "ns3/log.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("test-interference-helper");
bool checkResults = false;
bool expectRxASuccessfull = false;
bool expectRxBSuccessfull = false;
/// InterferenceExperiment
class InterferenceExperiment
{
@@ -71,12 +79,14 @@ public:
double xB; ///< x B
std::string txModeA; ///< transmit mode A
std::string txModeB; ///< transmit mode B
uint32_t txPowerLevelA; ///< transmit power level A
uint32_t txPowerLevelB; ///< transmit power level B
double txPowerLevelA; ///< transmit power level A
double txPowerLevelB; ///< transmit power level B
uint32_t packetSizeA; ///< packet size A
uint32_t packetSizeB; ///< packet size B
WifiPhyStandard standard; ///< standard
WifiPreamble preamble; ///< preamble
bool captureEnabled; ///< whether physical layer capture is enabled
double captureMargin; ///< margin used for physical layer capture
};
InterferenceExperiment ();
@@ -87,6 +97,8 @@ public:
void Run (struct InterferenceExperiment::Input input);
private:
/// Function triggered when a packet is dropped
void PacketDropped(Ptr<const Packet> packet);
/// Send A function
void SendA (void) const;
/// Send B function
@@ -94,6 +106,8 @@ private:
Ptr<YansWifiPhy> m_txA; ///< transmit A function
Ptr<YansWifiPhy> m_txB; ///< transmit B function
struct Input m_input; ///< input
bool m_droppedA; ///< flag to indicate whether packet A has been dropped
bool m_droppedB; ///< flag to indicate whether packet B has been dropped
};
void
@@ -118,21 +132,44 @@ InterferenceExperiment::SendB (void) const
m_txB->SendPacket (p, txVector);
}
void
InterferenceExperiment::PacketDropped(Ptr<const Packet> packet)
{
if (packet->GetUid () == 0)
{
m_droppedA = true;
}
else if (packet->GetUid () == 1)
{
m_droppedB = true;
}
else
{
NS_LOG_ERROR ("Unknown packet!");
exit (1);
}
}
InterferenceExperiment::InterferenceExperiment ()
: m_droppedA (false),
m_droppedB (false)
{
}
InterferenceExperiment::Input::Input ()
: interval (MicroSeconds (0)),
xA (-5),
xB (5),
txModeA ("OfdmRate54Mbps"),
txModeB ("OfdmRate54Mbps"),
txPowerLevelA (0),
txPowerLevelB (0),
txPowerLevelA (16.0206),
txPowerLevelB (16.0206),
packetSizeA (1500),
packetSizeB (1500),
standard (WIFI_PHY_STANDARD_80211a),
preamble (WIFI_PREAMBLE_LONG)
preamble (WIFI_PREAMBLE_LONG),
captureEnabled (false),
captureMargin (0)
{
}
@@ -157,7 +194,11 @@ InterferenceExperiment::Run (struct InterferenceExperiment::Input input)
posRx->SetPosition (Vector (0.0, 0.0, 0.0));
m_txA = CreateObject<YansWifiPhy> ();
m_txA->SetTxPowerStart (input.txPowerLevelA);
m_txA->SetTxPowerEnd (input.txPowerLevelA);
m_txB = CreateObject<YansWifiPhy> ();
m_txB->SetTxPowerStart (input.txPowerLevelB);
m_txB->SetTxPowerEnd (input.txPowerLevelB);
Ptr<YansWifiPhy> rx = CreateObject<YansWifiPhy> ();
Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel> ();
@@ -170,18 +211,31 @@ InterferenceExperiment::Run (struct InterferenceExperiment::Input input)
m_txA->SetMobility (posTxA);
m_txB->SetMobility (posTxB);
rx->SetMobility (posRx);
if (input.captureEnabled)
{
Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel> ();
frameCaptureModel->SetMargin (input.captureMargin);
rx->SetFrameCaptureModel (frameCaptureModel);
}
m_txA->ConfigureStandard (input.standard);
m_txB->ConfigureStandard (input.standard);
rx->ConfigureStandard (input.standard);
rx->TraceConnectWithoutContext("PhyRxDrop", MakeCallback(&InterferenceExperiment::PacketDropped, this));
Simulator::Schedule (Seconds (0), &InterferenceExperiment::SendA, this);
Simulator::Schedule (Seconds (0) + input.interval, &InterferenceExperiment::SendB, this);
Simulator::Run ();
Simulator::Destroy ();
}
if(checkResults && (m_droppedA == expectRxASuccessfull || m_droppedB == expectRxBSuccessfull))
{
NS_LOG_ERROR ("Results are not expected!");
exit (1);
}
}
int main (int argc, char *argv[])
{
@@ -202,10 +256,17 @@ int main (int argc, char *argv[])
cmd.AddValue ("txModeB", "Wifi mode used for payload transmission of sender B", input.txModeB);
cmd.AddValue ("standard", "IEEE 802.11 flavor", str_standard);
cmd.AddValue ("preamble", "Type of preamble", str_preamble);
cmd.AddValue ("enableCapture", "Enable/disable physical layer capture", input.captureEnabled);
cmd.AddValue ("captureMargin", "Margin used for physical layer capture", input.captureMargin);
cmd.AddValue ("checkResults", "Used to check results at the end of the test", checkResults);
cmd.AddValue ("expectRxASuccessfull", "Indicate whether packet A is expected to be successfully received", expectRxASuccessfull);
cmd.AddValue ("expectRxBSuccessfull", "Indicate whether packet B is expected to be successfully received", expectRxBSuccessfull);
cmd.Parse (argc, argv);
LogComponentEnable ("WifiPhy", LOG_LEVEL_ALL);
LogComponentEnable ("YansWifiPhy", LOG_LEVEL_ALL);
LogComponentEnable ("InterferenceHelper", LOG_LEVEL_ALL);
LogComponentEnable ("SimpleFrameCaptureModel", LOG_LEVEL_ALL);
input.interval = MicroSeconds (delay);

View File

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

View File

@@ -0,0 +1,60 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2017
*
* 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 FRAME_CAPTURE_MODEL_H
#define FRAME_CAPTURE_MODEL_H
#include "ns3/object.h"
#include "interference-helper.h"
namespace ns3 {
/**
* \ingroup wifi
* \brief the interface for Wifi's frame capture models
*
*/
class FrameCaptureModel : 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 reception should be switched to a
* new incoming frame.
*
* \param currentEvent the event of the current frame
* \param newEvent the event of the new incoming frame
*
* \return true if the reception should be switched to a new incoming frame,
* false otherwise
*/
virtual bool CaptureNewFrame (Ptr<InterferenceHelper::Event> currentEvent, Ptr<InterferenceHelper::Event> newEvent) const = 0;
};
} //namespace ns3
#endif /* FRAME_CAPTURE_MODEL_H */

View File

@@ -33,8 +33,9 @@ NS_LOG_COMPONENT_DEFINE ("InterferenceHelper");
* Phy event class
****************************************************************/
InterferenceHelper::Event::Event (WifiTxVector txVector, Time duration, double rxPower)
: m_txVector (txVector),
InterferenceHelper::Event::Event (Ptr<const Packet> packet, WifiTxVector txVector, Time duration, double rxPower)
: m_packet (packet),
m_txVector (txVector),
m_startTime (Simulator::Now ()),
m_endTime (m_startTime + duration),
m_rxPowerW (rxPower)
@@ -45,6 +46,12 @@ InterferenceHelper::Event::~Event ()
{
}
Ptr<const Packet>
InterferenceHelper::Event::GetPacket (void) const
{
return m_packet;
}
Time
InterferenceHelper::Event::GetDuration (void) const
{
@@ -87,9 +94,10 @@ InterferenceHelper::Event::GetPayloadMode (void) const
* short period of time.
****************************************************************/
InterferenceHelper::NiChange::NiChange (Time time, double delta)
InterferenceHelper::NiChange::NiChange (Time time, double delta, Ptr<InterferenceHelper::Event> event)
: m_time (time),
m_delta (delta)
m_delta (delta),
m_event (event)
{
}
@@ -105,6 +113,12 @@ InterferenceHelper::NiChange::GetDelta (void) const
return m_delta;
}
Ptr<InterferenceHelper::Event>
InterferenceHelper::NiChange::GetEvent (void) const
{
return m_event;
}
bool
InterferenceHelper::NiChange::operator < (const InterferenceHelper::NiChange& o) const
{
@@ -131,11 +145,10 @@ InterferenceHelper::~InterferenceHelper ()
}
Ptr<InterferenceHelper::Event>
InterferenceHelper::Add (WifiTxVector txVector, Time duration, double rxPowerW)
InterferenceHelper::Add (Ptr<const Packet> packet, WifiTxVector txVector, Time duration, double rxPowerW)
{
Ptr<InterferenceHelper::Event> event;
event = Create<InterferenceHelper::Event> (txVector, duration, rxPowerW);
event = Create<InterferenceHelper::Event> (packet, txVector, duration, rxPowerW);
AppendEvent (event);
return event;
}
@@ -146,7 +159,8 @@ InterferenceHelper::AddForeignSignal (Time duration, double rxPowerW)
// Parameters other than duration and rxPowerW are unused for this type
// of signal, so we provide dummy versions
WifiTxVector fakeTxVector;
Add (fakeTxVector, duration, rxPowerW);
Ptr<const Packet> packet (0);
Add (packet, fakeTxVector, duration, rxPowerW);
}
void
@@ -214,13 +228,13 @@ InterferenceHelper::AppendEvent (Ptr<InterferenceHelper::Event> event)
m_firstPower += i->GetDelta ();
}
m_niChanges.erase (m_niChanges.begin (), nowIterator);
m_niChanges.insert (m_niChanges.begin (), NiChange (event->GetStartTime (), event->GetRxPowerW ()));
m_niChanges.insert (m_niChanges.begin (), NiChange (event->GetStartTime (), event->GetRxPowerW (), event));
}
else
{
AddNiChangeEvent (NiChange (event->GetStartTime (), event->GetRxPowerW ()));
AddNiChangeEvent (NiChange (event->GetStartTime (), event->GetRxPowerW (), event));
}
AddNiChangeEvent (NiChange (event->GetEndTime (), -event->GetRxPowerW ()));
AddNiChangeEvent (NiChange (event->GetEndTime (), -event->GetRxPowerW (), event));
}
@@ -244,17 +258,41 @@ double
InterferenceHelper::CalculateNoiseInterferenceW (Ptr<InterferenceHelper::Event> event, NiChanges *ni) const
{
double noiseInterference = m_firstPower;
NS_ASSERT (m_rxing);
for (NiChanges::const_iterator i = m_niChanges.begin () + 1; i != m_niChanges.end (); i++)
NiChanges::const_iterator eventIterator = m_niChanges.begin ();
while (eventIterator != m_niChanges.end ())
{
if ((event->GetEndTime () == i->GetTime ()) && event->GetRxPowerW () == -i->GetDelta ())
// Iterate the NI change list from the beginning to the end
// until find the position of the event in the NI change list
// The reason of using the event that causes the NI change to identify
// different NI changes is because in some special cases
// different NI changes happen at the same time with the same delta
// value. Therefore, it may be impossible to identify a NI change that belongs
// to which event based on just the NI time and NI delta value
if (eventIterator->GetEvent () != event)
{
// The NI changes which happen before the event should be considered
// as the interference. This considers the case that the receiving event
// arrives while another receiving event is going on. The SINR of
// the newly arrived event is calculated for checking the possibility of frame capture
noiseInterference += eventIterator->GetDelta ();
}
else
{
break;
}
++eventIterator;
}
for (NiChanges::const_iterator i = eventIterator + 1; i != m_niChanges.end (); ++i)
{
if (event->GetEndTime () == i->GetTime () && event == i->GetEvent ())
{
break;
}
ni->push_back (*i);
}
ni->insert (ni->begin (), NiChange (event->GetStartTime (), noiseInterference));
ni->push_back (NiChange (event->GetEndTime (), 0));
ni->insert (ni->begin (), NiChange (event->GetStartTime (), noiseInterference, event));
ni->push_back (NiChange (event->GetEndTime (), 0, event));
return noiseInterference;
}
@@ -840,7 +878,7 @@ InterferenceHelper::EraseEvents (void)
InterferenceHelper::NiChanges::iterator
InterferenceHelper::GetPosition (Time moment)
{
return std::upper_bound (m_niChanges.begin (), m_niChanges.end (), NiChange (moment, 0));
return std::upper_bound (m_niChanges.begin (), m_niChanges.end (), NiChange (moment, 0, NULL));
}
void

View File

@@ -22,6 +22,7 @@
#define INTERFERENCE_HELPER_H
#include "ns3/nstime.h"
#include "ns3/packet.h"
#include "wifi-tx-vector.h"
#include "error-rate-model.h"
@@ -43,13 +44,19 @@ public:
/**
* Create an Event with the given parameters.
*
* \param packet the packet
* \param txVector TXVECTOR of the packet
* \param duration duration of the signal
* \param rxPower the receive power (w)
*/
Event (WifiTxVector txVector, Time duration, double rxPower);
Event (Ptr<const Packet> packet, WifiTxVector txVector, Time duration, double rxPower);
~Event ();
/** Return the packet.
*
* \return the packet
*/
Ptr<const Packet> GetPacket (void) const;
/**
* Return the duration of the signal.
*
@@ -89,6 +96,7 @@ public:
private:
Ptr<const Packet> m_packet; ///< packet
WifiTxVector m_txVector; ///< TXVECTOR
Time m_startTime; ///< start time
Time m_endTime; ///< end time
@@ -152,13 +160,14 @@ private:
/**
* Add the packet-related signal to interference helper.
*
* \param packet the packet
* \param txVector TXVECTOR of the packet
* \param duration the duration of the signal
* \param rxPower receive power (W)
*
* \return InterferenceHelper::Event
*/
Ptr<InterferenceHelper::Event> Add (WifiTxVector txVector, Time duration, double rxPower);
Ptr<InterferenceHelper::Event> Add (Ptr<const Packet> packet, WifiTxVector txVector, Time duration, double rxPower);
/**
* Add a non-Wifi signal to interference helper.
@@ -211,8 +220,9 @@ public:
*
* \param time time of the event
* \param delta the power
* \param event causes this NI change
*/
NiChange (Time time, double delta);
NiChange (Time time, double delta, Ptr<InterferenceHelper::Event> event);
/**
* Return the event time.
*
@@ -225,6 +235,12 @@ public:
* \return the power
*/
double GetDelta (void) const;
/**
* Return the event causes the corresponding NI change
*
* \return the event
*/
Ptr<InterferenceHelper::Event> GetEvent (void) const;
/**
* Compare the event time of two NiChange objects (a < o).
*
@@ -237,6 +253,7 @@ public:
private:
Time m_time; ///< time
double m_delta; ///< delta
Ptr<InterferenceHelper::Event> m_event;
};
/**
* typedef for a vector of NiChanges
@@ -309,6 +326,7 @@ private:
NiChanges m_niChanges;
double m_firstPower; ///< first power
bool m_rxing; ///< flag whether it is in receiving state
/// Returns an iterator to the first nichange, which is later than moment
NiChanges::iterator GetPosition (Time moment);
/**

View File

@@ -0,0 +1,88 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2017
*
* 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 "simple-frame-capture-model.h"
#include "ns3/simulator.h"
#include "ns3/log.h"
#include "ns3/double.h"
#include "wifi-utils.h"
#include "wifi-phy.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("SimpleFrameCaptureModel");
NS_OBJECT_ENSURE_REGISTERED (SimpleFrameCaptureModel);
TypeId
SimpleFrameCaptureModel::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::SimpleFrameCaptureModel")
.SetParent<FrameCaptureModel> ()
.SetGroupName ("Wifi")
.AddConstructor<SimpleFrameCaptureModel> ()
.AddAttribute ("Margin",
"Reception is switched if the newly arrived frame has a power higher than "
"this value above the frame currently being received (expressed in dB).",
DoubleValue (10),
MakeDoubleAccessor (&SimpleFrameCaptureModel::GetMargin,
&SimpleFrameCaptureModel::SetMargin),
MakeDoubleChecker<double> ())
;
return tid;
}
SimpleFrameCaptureModel::SimpleFrameCaptureModel ()
{
NS_LOG_FUNCTION (this);
}
SimpleFrameCaptureModel::~SimpleFrameCaptureModel ()
{
NS_LOG_FUNCTION (this);
}
void
SimpleFrameCaptureModel::SetMargin (double margin)
{
NS_LOG_FUNCTION (this << margin);
m_margin = margin;
}
double
SimpleFrameCaptureModel::GetMargin (void) const
{
return m_margin;
}
bool
SimpleFrameCaptureModel::CaptureNewFrame (Ptr<InterferenceHelper::Event> currentEvent, Ptr<InterferenceHelper::Event> newEvent) const
{
NS_LOG_FUNCTION (this);
if (newEvent->GetTxVector ().GetPreambleType () != WIFI_PREAMBLE_NONE
&& (WToDbm (currentEvent->GetRxPowerW ()) + m_margin) < WToDbm (newEvent->GetRxPowerW ())
&& ((currentEvent->GetStartTime () + WifiPhy::CalculatePlcpPreambleAndHeaderDuration (currentEvent->GetTxVector ())) > Simulator::Now ()))
{
return true;
}
return false;
}
} //namespace ns3

View File

@@ -0,0 +1,82 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2017
*
* 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 SIMPLE_FRAME_CAPTURE_MODEL_H
#define SIMPLE_FRAME_CAPTURE_MODEL_H
#include "frame-capture-model.h"
namespace ns3 {
/**
* \ingroup wifi
*
* A simple threshold-based model for frame capture effect.
* If the new incoming frame arrives while the receiver is
* receiving the preamble of another frame and the SIR of
* the new incoming frame is above a fixed margin, then
* the current frame is dropped and the receiver locks
* onto the new incoming frame.
*/
class SimpleFrameCaptureModel : public FrameCaptureModel
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
SimpleFrameCaptureModel ();
~SimpleFrameCaptureModel ();
/**
* Sets the frame capture margin (dB).
*
* \param margin the frame capture margin in dB
*/
void SetMargin (double margin);
/**
* Return the frame capture margin (dB).
*
* \return the frame capture margin in dB
*/
double GetMargin (void) const;
/**
* This method returns whether the reception should be switched to a
* new incoming frame.
*
* \param currentEvent the event of the current frame
* \param newEvent the event of the new incoming frame
*
* \return true if the reception should be switched to a new incoming frame,
* false otherwise
*/
bool CaptureNewFrame (Ptr<InterferenceHelper::Event> currentEvent, Ptr<InterferenceHelper::Event> newEvent) const;
private:
double m_margin;
};
} //namespace ns3
#endif /* SIMPLE_FRAME_CAPTURE_MODEL_H */

View File

@@ -221,6 +221,7 @@ WifiPhyStateHelper::GetState (void) const
void
WifiPhyStateHelper::NotifyTxStart (Time duration, double txPowerDbm)
{
NS_LOG_FUNCTION (this);
for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
{
(*i)->NotifyTxStart (duration, txPowerDbm);
@@ -230,6 +231,7 @@ WifiPhyStateHelper::NotifyTxStart (Time duration, double txPowerDbm)
void
WifiPhyStateHelper::NotifyRxStart (Time duration)
{
NS_LOG_FUNCTION (this);
for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
{
(*i)->NotifyRxStart (duration);
@@ -239,6 +241,7 @@ WifiPhyStateHelper::NotifyRxStart (Time duration)
void
WifiPhyStateHelper::NotifyRxEndOk (void)
{
NS_LOG_FUNCTION (this);
for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
{
(*i)->NotifyRxEndOk ();
@@ -248,6 +251,7 @@ WifiPhyStateHelper::NotifyRxEndOk (void)
void
WifiPhyStateHelper::NotifyRxEndError (void)
{
NS_LOG_FUNCTION (this);
for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
{
(*i)->NotifyRxEndError ();
@@ -257,6 +261,7 @@ WifiPhyStateHelper::NotifyRxEndError (void)
void
WifiPhyStateHelper::NotifyMaybeCcaBusyStart (Time duration)
{
NS_LOG_FUNCTION (this);
for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
{
(*i)->NotifyMaybeCcaBusyStart (duration);
@@ -266,6 +271,7 @@ WifiPhyStateHelper::NotifyMaybeCcaBusyStart (Time duration)
void
WifiPhyStateHelper::NotifySwitchingStart (Time duration)
{
NS_LOG_FUNCTION (this);
for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
{
(*i)->NotifySwitchingStart (duration);
@@ -275,6 +281,7 @@ WifiPhyStateHelper::NotifySwitchingStart (Time duration)
void
WifiPhyStateHelper::NotifySleep (void)
{
NS_LOG_FUNCTION (this);
for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
{
(*i)->NotifySleep ();
@@ -284,6 +291,7 @@ WifiPhyStateHelper::NotifySleep (void)
void
WifiPhyStateHelper::NotifyWakeup (void)
{
NS_LOG_FUNCTION (this);
for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++)
{
(*i)->NotifyWakeup ();
@@ -293,6 +301,7 @@ WifiPhyStateHelper::NotifyWakeup (void)
void
WifiPhyStateHelper::LogPreviousIdleAndCcaBusyStates (void)
{
NS_LOG_FUNCTION (this);
Time now = Simulator::Now ();
Time idleStart = Max (m_endCcaBusy, m_endRx);
idleStart = Max (idleStart, m_endTx);
@@ -314,6 +323,7 @@ void
WifiPhyStateHelper::SwitchToTx (Time txDuration, Ptr<const Packet> packet, double txPowerDbm,
WifiTxVector txVector)
{
NS_LOG_FUNCTION (this << txDuration << packet << txPowerDbm << txVector);
m_txTrace (packet, txVector.GetMode (), txVector.GetPreambleType (), txVector.GetTxPowerLevel ());
Time now = Simulator::Now ();
switch (GetState ())
@@ -352,6 +362,7 @@ WifiPhyStateHelper::SwitchToTx (Time txDuration, Ptr<const Packet> packet, doubl
void
WifiPhyStateHelper::SwitchToRx (Time rxDuration)
{
NS_LOG_FUNCTION (this << rxDuration);
NS_ASSERT (IsStateIdle () || IsStateCcaBusy ());
NS_ASSERT (!m_rxing);
Time now = Simulator::Now ();
@@ -385,6 +396,7 @@ WifiPhyStateHelper::SwitchToRx (Time rxDuration)
void
WifiPhyStateHelper::SwitchToChannelSwitching (Time switchingDuration)
{
NS_LOG_FUNCTION (this << switchingDuration);
Time now = Simulator::Now ();
switch (GetState ())
{
@@ -430,6 +442,7 @@ WifiPhyStateHelper::SwitchToChannelSwitching (Time switchingDuration)
void
WifiPhyStateHelper::SwitchFromRxEndOk (Ptr<Packet> packet, double snr, WifiTxVector txVector)
{
NS_LOG_FUNCTION (this << packet << snr << txVector);
m_rxOkTrace (packet, snr, txVector.GetMode (), txVector.GetPreambleType ());
NotifyRxEndOk ();
DoSwitchFromRx ();
@@ -443,6 +456,7 @@ WifiPhyStateHelper::SwitchFromRxEndOk (Ptr<Packet> packet, double snr, WifiTxVec
void
WifiPhyStateHelper::SwitchFromRxEndError (Ptr<Packet> packet, double snr)
{
NS_LOG_FUNCTION (this << packet << snr);
m_rxErrorTrace (packet, snr);
NotifyRxEndError ();
DoSwitchFromRx ();
@@ -455,6 +469,7 @@ WifiPhyStateHelper::SwitchFromRxEndError (Ptr<Packet> packet, double snr)
void
WifiPhyStateHelper::DoSwitchFromRx (void)
{
NS_LOG_FUNCTION (this);
NS_ASSERT (IsStateRx ());
NS_ASSERT (m_rxing);
@@ -469,6 +484,7 @@ WifiPhyStateHelper::DoSwitchFromRx (void)
void
WifiPhyStateHelper::SwitchMaybeToCcaBusy (Time duration)
{
NS_LOG_FUNCTION (this << duration);
NotifyMaybeCcaBusyStart (duration);
Time now = Simulator::Now ();
switch (GetState ())
@@ -497,6 +513,7 @@ WifiPhyStateHelper::SwitchMaybeToCcaBusy (Time duration)
void
WifiPhyStateHelper::SwitchToSleep (void)
{
NS_LOG_FUNCTION (this);
Time now = Simulator::Now ();
switch (GetState ())
{
@@ -527,6 +544,7 @@ WifiPhyStateHelper::SwitchToSleep (void)
void
WifiPhyStateHelper::SwitchFromSleep (Time duration)
{
NS_LOG_FUNCTION (this << duration);
NS_ASSERT (IsStateSleep ());
Time now = Simulator::Now ();
m_stateLogger (m_startSleep, now - m_startSleep, WifiPhy::SLEEP);
@@ -541,4 +559,15 @@ WifiPhyStateHelper::SwitchFromSleep (Time duration)
}
}
void
WifiPhyStateHelper::SwitchFromRxAbort (void)
{
NS_LOG_FUNCTION (this);
NS_ASSERT (IsStateRx ());
NS_ASSERT (m_rxing);
m_endRx = Simulator::Now ();
DoSwitchFromRx ();
NS_ASSERT (!IsStateRx ());
}
} //namespace ns3

View File

@@ -185,6 +185,10 @@ public:
* \param duration the duration of CCA busy state
*/
void SwitchFromSleep (Time duration);
/**
* Abort current reception
*/
void SwitchFromRxAbort (void);
/**
* TracedCallback signature for state changes.

View File

@@ -30,6 +30,7 @@
#include "wifi-phy-tag.h"
#include "ampdu-tag.h"
#include "wifi-utils.h"
#include "frame-capture-model.h"
namespace ns3 {
@@ -314,6 +315,12 @@ WifiPhy::GetTypeId (void)
MakeBooleanAccessor (&WifiPhy::GetShortPlcpPreambleSupported,
&WifiPhy::SetShortPlcpPreambleSupported),
MakeBooleanChecker ())
.AddAttribute ("FrameCaptureModel",
"Ptr to an object that implements the frame capture model",
PointerValue (0), //StringValue ("ns3::SimpleFrameCaptureModel"),
MakePointerAccessor (&WifiPhy::GetFrameCaptureModel,
&WifiPhy::SetFrameCaptureModel),
MakePointerChecker <FrameCaptureModel>())
.AddTraceSource ("PhyTxBegin",
"Trace source indicating a packet "
"has begun transmitting over the channel medium",
@@ -378,7 +385,8 @@ WifiPhy::WifiPhy ()
m_channelNumber (0),
m_initialChannelNumber (0),
m_totalAmpduSize (0),
m_totalAmpduNumSymbols (0)
m_totalAmpduNumSymbols (0),
m_currentEvent (0)
{
NS_LOG_FUNCTION (this);
NS_UNUSED (m_numberOfTransmitters);
@@ -702,6 +710,18 @@ WifiPhy::GetErrorRateModel (void) const
return m_interference.GetErrorRateModel ();
}
void
WifiPhy::SetFrameCaptureModel (Ptr<FrameCaptureModel> model)
{
m_frameCaptureModel = model;
}
Ptr<FrameCaptureModel>
WifiPhy::GetFrameCaptureModel (void) const
{
return m_frameCaptureModel;
}
double
WifiPhy::GetPowerDbm (uint8_t power) const
{
@@ -2356,7 +2376,6 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerW, Tim
//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;
@@ -2380,15 +2399,13 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerW, Tim
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 (txVector,
event = m_interference.Add (packet,
txVector,
rxDuration,
rxPowerW);
MpduType mpdutype = tag.GetMpduType ();
switch (m_state->GetState ())
{
case WifiPhy::SWITCHING:
@@ -2407,18 +2424,31 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerW, Tim
{
//that packet will be noise _after_ the completion of the
//channel switching.
goto maybeCcaBusy;
MaybeCcaBusyDuration ();
return;
}
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 ())
NS_ASSERT (m_currentEvent != 0);
if (m_frameCaptureModel != 0 &&
m_frameCaptureModel->CaptureNewFrame(m_currentEvent, event))
{
//that packet will be noise _after_ the reception of the
//currently-received packet.
goto maybeCcaBusy;
AbortCurrentReception ();
NS_LOG_DEBUG ("Switch to new packet");
StartRx (packet, txVector, mpdutype, rxPowerW, rxDuration, event);
}
else
{
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.
MaybeCcaBusyDuration ();
return;
}
}
break;
case WifiPhy::TX:
@@ -2429,77 +2459,13 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerW, Tim
{
//that packet will be noise _after_ the transmission of the
//currently-transmitted packet.
goto maybeCcaBusy;
MaybeCcaBusyDuration ();
return;
}
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;
}
StartRx (packet, txVector, mpdutype, rxPowerW, rxDuration, event);
break;
case WifiPhy::SLEEP:
NS_LOG_DEBUG ("drop packet because in sleep mode");
@@ -2507,10 +2473,11 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerW, Tim
m_plcpSuccess = false;
break;
}
}
return;
maybeCcaBusy:
void
WifiPhy::MaybeCcaBusyDuration ()
{
//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
@@ -2571,6 +2538,7 @@ WifiPhy::EndReceive (Ptr<Packet> packet, WifiPreamble preamble, MpduType mpdutyp
InterferenceHelper::SnrPer snrPer;
snrPer = m_interference.CalculatePlcpPayloadSnrPer (event);
m_interference.NotifyRxEnd ();
m_currentEvent = 0;
if (m_plcpSuccess == true)
{
@@ -3661,6 +3629,100 @@ WifiPhy::SwitchMaybeToCcaBusy (void)
}
}
void
WifiPhy::AbortCurrentReception ()
{
NS_LOG_FUNCTION (this);
if (m_endPlcpRxEvent.IsRunning ())
{
m_endPlcpRxEvent.Cancel ();
}
if (m_endRxEvent.IsRunning ())
{
m_endRxEvent.Cancel ();
}
NotifyRxDrop (m_currentEvent->GetPacket ());
m_interference.NotifyRxEnd ();
m_state->SwitchFromRxAbort ();
m_currentEvent = 0;
}
void
WifiPhy::StartRx (Ptr<Packet> packet, WifiTxVector txVector, MpduType mpdutype, double rxPowerW, Time rxDuration, Ptr<InterferenceHelper::Event> event)
{
NS_LOG_FUNCTION (this << packet << txVector << (uint16_t)mpdutype << rxPowerW << rxDuration);
if (rxPowerW > GetEdThresholdW ()) //checked here, no need to check in the payload reception (current implementation assumes constant rx power over the packet duration)
{
AmpduTag ampduTag;
WifiPreamble preamble = txVector.GetPreambleType ();
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);
MaybeCcaBusyDuration ();
return;
}
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)");
m_currentEvent = event;
m_state->SwitchToRx (rxDuration);
NS_ASSERT (m_endPlcpRxEvent.IsExpired ());
NotifyRxBegin (packet);
m_interference.NotifyRxStart ();
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);
}
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;
MaybeCcaBusyDuration ();
}
}
int64_t
WifiPhy::AssignStreams (int64_t stream)
{

View File

@@ -25,13 +25,13 @@
#include <map>
#include "ns3/callback.h"
#include "ns3/event-id.h"
#include "ns3/packet.h"
#include "ns3/mobility-model.h"
#include "ns3/random-variable-stream.h"
#include "ns3/channel.h"
#include "wifi-phy-standard.h"
#include "interference-helper.h"
#include "ns3/node.h"
#include "ns3/string.h"
namespace ns3 {
@@ -44,6 +44,11 @@ namespace ns3 {
*/
class WifiPhyStateHelper;
/**
* FrameCaptureModel class
*/
class FrameCaptureModel;
/**
* This enumeration defines the type of an MPDU.
*/
@@ -371,7 +376,7 @@ public:
*
* \return the total amount of time this PHY will stay busy for the transmission of the PLCP preamble and PLCP header.
*/
Time CalculatePlcpPreambleAndHeaderDuration (WifiTxVector txVector);
static Time CalculatePlcpPreambleAndHeaderDuration (WifiTxVector txVector);
/**
* \param txVector the transmission parameters used for this packet
@@ -1445,6 +1450,7 @@ public:
* \return the reception gain in dB
*/
double GetRxGain (void) const;
/**
* Sets the device this PHY is associated with.
*
@@ -1602,6 +1608,19 @@ public:
*/
Ptr<ErrorRateModel> GetErrorRateModel (void) const;
/**
* Sets the frame capture model.
*
* \param rate the frame capture model
*/
void SetFrameCaptureModel (Ptr<FrameCaptureModel> rate);
/**
* Return the frame capture model this PHY is using.
*
* \return the frame capture model this PHY is using
*/
Ptr<FrameCaptureModel> GetFrameCaptureModel (void) const;
/**
* \return the channel width
*/
@@ -1771,6 +1790,34 @@ private:
* \return the FrequencyWidthPair found
*/
FrequencyWidthPair GetFrequencyWidthForChannelNumberStandard (uint8_t channelNumber, WifiPhyStandard standard) const;
/**
* Due to newly arrived signal, the current reception cannot be continued and has to be aborted
*
*/
void AbortCurrentReception (void);
/**
* Eventually switch to CCA busy
*/
void MaybeCcaBusyDuration (void);
/**
* Starting receiving the packet after having detected the medium is idle or after a reception switch.
*
* \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 rxPowerW the receive power in W
* \param rxDuration the duration needed for the reception of the packet
* \param event the corresponding event of the first time the packet arrives
*/
void StartRx (Ptr<Packet> packet,
WifiTxVector txVector,
MpduType mpdutype,
double rxPowerW,
Time rxDuration,
Ptr<InterferenceHelper::Event> event);
/**
* The trace source fired when a packet begins the transmission process on
@@ -1931,6 +1978,9 @@ private:
Ptr<NetDevice> m_device; //!< Pointer to the device
Ptr<MobilityModel> m_mobility; //!< Pointer to the mobility model
Ptr<InterferenceHelper::Event> m_currentEvent; //!< Hold the current event
Ptr<FrameCaptureModel> m_frameCaptureModel; //!< Frame capture model
};
/**

View File

@@ -343,6 +343,8 @@ cpp_examples = [
("wifi-manager-example --wifiManager=Ideal --standard=802.11ax-2.4GHz --serverChannelWidth=40 --clientChannelWidth=40 --serverShortGuardInterval=800 --clientShortGuardInterval=800 --serverNss=4 --clientNss=4 --stepTime=0.1", "False", "False"),
("wifi-manager-example --wifiManager=Ideal --standard=802.11ax-2.4GHz --serverChannelWidth=40 --clientChannelWidth=40 --serverShortGuardInterval=1600 --clientShortGuardInterval=1600 --serverNss=4 --clientNss=4 --stepTime=0.1", "False", "False"),
("wifi-manager-example --wifiManager=Ideal --standard=802.11ax-2.4GHz --serverChannelWidth=40 --clientChannelWidth=40 --serverShortGuardInterval=3200 --clientShortGuardInterval=3200 --serverNss=4 --clientNss=4 --stepTime=0.1", "False", "False"),
("test-interference-helper --enableCapture=0 --txPowerA=5 --txPowerB=15 --delay=10 --txModeA=OfdmRate6Mbps --txModeB=OfdmRate6Mbps --checkResults=1 --expectRxASuccessfull=0 --expectRxBSuccessfull=0", "True", "True"),
("test-interference-helper --enableCapture=1 --txPowerA=5 --txPowerB=15 --delay=10 --txModeA=OfdmRate6Mbps --txModeB=OfdmRate6Mbps --checkResults=1 --expectRxASuccessfull=0 --expectRxBSuccessfull=1", "True", "True"),
]
# A list of Python examples to run in order to ensure that they remain

View File

@@ -83,6 +83,8 @@ def build(bld):
'model/dsss-parameter-set.cc',
'model/edca-parameter-set.cc',
'model/he-capabilities.cc',
'model/frame-capture-model.cc',
'model/simple-frame-capture-model.cc',
'helper/wifi-radio-energy-model-helper.cc',
'helper/vht-wifi-mac-helper.cc',
'helper/ht-wifi-mac-helper.cc',
@@ -190,6 +192,8 @@ def build(bld):
'model/dsss-parameter-set.h',
'model/edca-parameter-set.h',
'model/he-capabilities.h',
'model/frame-capture-model.h',
'model/simple-frame-capture-model.h',
'helper/wifi-radio-energy-model-helper.h',
'helper/vht-wifi-mac-helper.h',
'helper/ht-wifi-mac-helper.h',