wifi: (fixes #2791) rework InterferenceHelper

This commit is contained in:
Sébastien Deronne
2018-02-23 22:23:41 +01:00
parent f70318144d
commit e136b8eb0a
3 changed files with 120 additions and 122 deletions

View File

@@ -43,6 +43,7 @@ Bugs fixed
- Bug 2764 - wifi: WifiSpectrumModelId doesn't distinguish 11ax from legacy
- Bug 2766 - core: Modify logging for int64x64 to avoid stack overflow
- Bug 2768 - lte: LteUeNetDevice has a null MAC address
- Bug 2791 - wifi: Interference Helper gives negative trace value for Interference Power
- Bug 2807 - energy: GetTotalEnergyConsumption is not updated correctly
- Bug 2809 - wifi: Wifi doesn't fully stop when energy is depleted
- Bug 2813 - wifi: OFDM 10 MHz and 5 MHz PHYs do not have correct subcarrier frequency spacings

View File

@@ -88,23 +88,22 @@ InterferenceHelper::Event::GetPayloadMode (void) const
* short period of time.
****************************************************************/
InterferenceHelper::NiChange::NiChange (Time time, double delta, Ptr<InterferenceHelper::Event> event)
: m_time (time),
m_delta (delta),
InterferenceHelper::NiChange::NiChange (double power, Ptr<InterferenceHelper::Event> event)
: m_power (power),
m_event (event)
{
}
Time
InterferenceHelper::NiChange::GetTime (void) const
double
InterferenceHelper::NiChange::GetPower (void) const
{
return m_time;
return m_power;
}
double
InterferenceHelper::NiChange::GetDelta (void) const
void
InterferenceHelper::NiChange::AddPower (double power)
{
return m_delta;
m_power += power;
}
Ptr<InterferenceHelper::Event>
@@ -113,12 +112,6 @@ InterferenceHelper::NiChange::GetEvent (void) const
return m_event;
}
bool
InterferenceHelper::NiChange::operator < (const InterferenceHelper::NiChange& o) const
{
return (m_time < o.m_time);
}
/****************************************************************
* The actual InterferenceHelper
@@ -130,6 +123,8 @@ InterferenceHelper::InterferenceHelper ()
m_firstPower (0),
m_rxing (false)
{
// Always have a zero power noise event in the list
AddNiChangeEvent (Time (0), NiChange (0.0, 0));
}
InterferenceHelper::~InterferenceHelper ()
@@ -141,8 +136,7 @@ InterferenceHelper::~InterferenceHelper ()
Ptr<InterferenceHelper::Event>
InterferenceHelper::Add (Ptr<const Packet> packet, WifiTxVector txVector, Time duration, double rxPowerW)
{
Ptr<InterferenceHelper::Event> event;
event = Create<InterferenceHelper::Event> (packet, txVector, duration, rxPowerW);
Ptr<InterferenceHelper::Event> event = Create<InterferenceHelper::Event> (packet, txVector, duration, rxPowerW);
AppendEvent (event);
return event;
}
@@ -191,17 +185,12 @@ Time
InterferenceHelper::GetEnergyDuration (double energyW) const
{
Time now = Simulator::Now ();
double noiseInterferenceW = 0;
Time end = now;
noiseInterferenceW = m_firstPower;
for (NiChanges::const_iterator i = m_niChanges.begin (); i != m_niChanges.end (); i++)
auto i = GetPreviousPosition (now);
Time end = i->first;
for (; i != m_niChanges.end (); ++i)
{
noiseInterferenceW += i->GetDelta ();
end = i->GetTime ();
if (end < now)
{
continue;
}
double noiseInterferenceW = i->second.GetPower ();
end = i->first;
if (noiseInterferenceW < energyW)
{
break;
@@ -213,18 +202,25 @@ InterferenceHelper::GetEnergyDuration (double energyW) const
void
InterferenceHelper::AppendEvent (Ptr<InterferenceHelper::Event> event)
{
Time now = Simulator::Now ();
NS_LOG_FUNCTION (this);
double previousPowerStart = 0;
double previousPowerEnd = 0;
previousPowerStart = GetPreviousPosition (event->GetStartTime ())->second.GetPower ();
previousPowerEnd = GetPreviousPosition (event->GetEndTime ())->second.GetPower ();
if (!m_rxing)
{
NiChanges::const_iterator nowIterator = GetPosition (now);
for (NiChanges::const_iterator i = m_niChanges.begin (); i != nowIterator; i++)
{
m_firstPower += i->GetDelta ();
}
m_niChanges.erase (m_niChanges.begin (), nowIterator);
m_firstPower = previousPowerStart;
// Always leave the first zero power noise event in the list
m_niChanges.erase (++(m_niChanges.begin ()),
GetNextPosition (event->GetStartTime ()));
}
auto first = AddNiChangeEvent (event->GetStartTime (), NiChange (previousPowerStart, event));
auto last = AddNiChangeEvent (event->GetEndTime (), NiChange (previousPowerEnd, event));
for (auto i = first; i != last; ++i)
{
i->second.AddPower (event->GetRxPowerW ());
}
AddNiChangeEvent (NiChange (event->GetStartTime (), event->GetRxPowerW (), event));
AddNiChangeEvent (NiChange (event->GetEndTime (), -event->GetRxPowerW (), event));
}
double
@@ -246,41 +242,19 @@ double
InterferenceHelper::CalculateNoiseInterferenceW (Ptr<InterferenceHelper::Event> event, NiChanges *ni) const
{
double noiseInterference = m_firstPower;
NiChanges::const_iterator eventIterator = m_niChanges.begin ();
while (eventIterator != m_niChanges.end ())
auto it = m_niChanges.find (event->GetStartTime ());
for (; it != m_niChanges.end () && it->second.GetEvent () != event; ++it)
{
// 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;
noiseInterference = it->second.GetPower ();
}
for (NiChanges::const_iterator i = eventIterator + 1; i != m_niChanges.end (); ++i)
ni->emplace (event->GetStartTime (), NiChange (0, event));
while (++it != m_niChanges.end () && it->second.GetEvent () != event)
{
if (event->GetEndTime () == i->GetTime () && event == i->GetEvent ())
{
break;
}
ni->push_back (*i);
ni->insert (*it);
}
ni->insert (ni->begin (), NiChange (event->GetStartTime (), noiseInterference, event));
ni->push_back (NiChange (event->GetEndTime (), 0, event));
ni->emplace (event->GetEndTime (), NiChange (0, event));
NS_ABORT_MSG_IF (noiseInterference < 0, "noiseInterference < 0: " <<
noiseInterference);
return noiseInterference;
}
@@ -312,20 +286,19 @@ InterferenceHelper::CalculatePlcpPayloadPer (Ptr<const InterferenceHelper::Event
NS_LOG_FUNCTION (this);
const WifiTxVector txVector = event->GetTxVector ();
double psr = 1.0; /* Packet Success Rate */
NiChanges::const_iterator j = ni->begin ();
Time previous = (*j).GetTime ();
auto j = ni->begin ();
Time previous = j->first;
WifiMode payloadMode = event->GetPayloadMode ();
WifiPreamble preamble = txVector.GetPreambleType ();
Time plcpHeaderStart = (*j).GetTime () + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble
Time plcpHeaderStart = j->first + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble
Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (txVector); //packet start time + preamble + L-SIG
Time plcpTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble) + WifiPhy::GetPlcpSigA1Duration (preamble) + WifiPhy::GetPlcpSigA2Duration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A
Time plcpPayloadStart = plcpTrainingSymbolsStart + WifiPhy::GetPlcpTrainingSymbolDuration (txVector) + WifiPhy::GetPlcpSigBDuration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B
double noiseInterferenceW = (*j).GetDelta ();
double noiseInterferenceW = m_firstPower;
double powerW = event->GetRxPowerW ();
j++;
while (ni->end () != j)
while (++j != ni->end ())
{
Time current = (*j).GetTime ();
Time current = j->first;
NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
NS_ASSERT (current >= previous);
//Case 1: Both previous and current point to the payload
@@ -348,9 +321,8 @@ InterferenceHelper::CalculatePlcpPayloadPer (Ptr<const InterferenceHelper::Event
payloadMode, txVector);
NS_LOG_DEBUG ("previous is before payload and current is in the payload: mode=" << payloadMode << ", psr=" << psr);
}
noiseInterferenceW += (*j).GetDelta ();
previous = (*j).GetTime ();
j++;
noiseInterferenceW = j->second.GetPower () - powerW;
previous = j->first;
}
double per = 1 - psr;
return per;
@@ -362,8 +334,8 @@ InterferenceHelper::CalculatePlcpHeaderPer (Ptr<const InterferenceHelper::Event>
NS_LOG_FUNCTION (this);
const WifiTxVector txVector = event->GetTxVector ();
double psr = 1.0; /* Packet Success Rate */
NiChanges::const_iterator j = ni->begin ();
Time previous = (*j).GetTime ();
auto j = ni->begin ();
Time previous = j->first;
WifiPreamble preamble = txVector.GetPreambleType ();
WifiMode mcsHeaderMode;
if (preamble == WIFI_PREAMBLE_HT_MF || preamble == WIFI_PREAMBLE_HT_GF)
@@ -382,16 +354,15 @@ InterferenceHelper::CalculatePlcpHeaderPer (Ptr<const InterferenceHelper::Event>
mcsHeaderMode = WifiPhy::GetHePlcpHeaderMode ();
}
WifiMode headerMode = WifiPhy::GetPlcpHeaderMode (txVector);
Time plcpHeaderStart = (*j).GetTime () + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble
Time plcpHeaderStart = j->first + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble
Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (txVector); //packet start time + preamble + L-SIG
Time plcpTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble) + WifiPhy::GetPlcpSigA1Duration (preamble) + WifiPhy::GetPlcpSigA2Duration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A
Time plcpPayloadStart = plcpTrainingSymbolsStart + WifiPhy::GetPlcpTrainingSymbolDuration (txVector) + WifiPhy::GetPlcpSigBDuration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B
double noiseInterferenceW = (*j).GetDelta ();
double noiseInterferenceW = m_firstPower;
double powerW = event->GetRxPowerW ();
j++;
while (ni->end () != j)
while (++j != ni->end ())
{
Time current = (*j).GetTime ();
Time current = j->first;
NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
NS_ASSERT (current >= previous);
//Case 1: previous and current after playload start: nothing to do
@@ -764,9 +735,8 @@ InterferenceHelper::CalculatePlcpHeaderPer (Ptr<const InterferenceHelper::Event>
}
}
noiseInterferenceW += (*j).GetDelta ();
previous = (*j).GetTime ();
j++;
noiseInterferenceW = j->second.GetPower () - powerW;
previous = j->first;
}
double per = 1 - psr;
@@ -774,7 +744,7 @@ InterferenceHelper::CalculatePlcpHeaderPer (Ptr<const InterferenceHelper::Event>
}
struct InterferenceHelper::SnrPer
InterferenceHelper::CalculatePlcpPayloadSnrPer (Ptr<InterferenceHelper::Event> event)
InterferenceHelper::CalculatePlcpPayloadSnrPer (Ptr<InterferenceHelper::Event> event) const
{
NiChanges ni;
double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
@@ -794,7 +764,7 @@ InterferenceHelper::CalculatePlcpPayloadSnrPer (Ptr<InterferenceHelper::Event> e
}
struct InterferenceHelper::SnrPer
InterferenceHelper::CalculatePlcpHeaderSnrPer (Ptr<InterferenceHelper::Event> event)
InterferenceHelper::CalculatePlcpHeaderSnrPer (Ptr<InterferenceHelper::Event> event) const
{
NiChanges ni;
double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
@@ -817,20 +787,32 @@ void
InterferenceHelper::EraseEvents (void)
{
m_niChanges.clear ();
// Always have a zero power noise event in the list
AddNiChangeEvent (Time (0), NiChange (0.0, 0));
m_rxing = false;
m_firstPower = 0;
}
InterferenceHelper::NiChanges::const_iterator
InterferenceHelper::GetPosition (Time moment)
InterferenceHelper::GetNextPosition (Time moment) const
{
return std::upper_bound (m_niChanges.begin (), m_niChanges.end (), NiChange (moment, 0, NULL));
return m_niChanges.upper_bound (moment);
}
void
InterferenceHelper::AddNiChangeEvent (NiChange change)
InterferenceHelper::NiChanges::const_iterator
InterferenceHelper::GetPreviousPosition (Time moment) const
{
m_niChanges.insert (GetPosition (change.GetTime ()), change);
auto it = GetNextPosition (moment);
// This is safe since there is always an NiChange at time 0,
// before moment.
--it;
return it;
}
InterferenceHelper::NiChanges::iterator
InterferenceHelper::AddNiChangeEvent (Time moment, NiChange change)
{
return m_niChanges.insert (GetNextPosition (moment), std::make_pair (moment, change));
}
void
@@ -845,6 +827,10 @@ InterferenceHelper::NotifyRxEnd ()
{
NS_LOG_FUNCTION (this);
m_rxing = false;
//Update m_firstPower for frame capture
auto it = m_niChanges.find (Simulator::Now ());
it--;
m_firstPower = it->second.GetPower ();
}
} //namespace ns3

View File

@@ -25,6 +25,7 @@
#include "ns3/packet.h"
#include "wifi-tx-vector.h"
#include "error-rate-model.h"
#include <map>
namespace ns3 {
@@ -177,7 +178,7 @@ private:
*
* \return struct of SNR and PER
*/
struct InterferenceHelper::SnrPer CalculatePlcpPayloadSnrPer (Ptr<InterferenceHelper::Event> event);
struct InterferenceHelper::SnrPer CalculatePlcpPayloadSnrPer (Ptr<InterferenceHelper::Event> event) const;
/**
* Calculate the SNIR at the start of the plcp header and accumulate
* all SNIR changes in the snir vector.
@@ -186,7 +187,7 @@ private:
*
* \return struct of SNR and PER
*/
struct InterferenceHelper::SnrPer CalculatePlcpHeaderSnrPer (Ptr<InterferenceHelper::Event> event);
struct InterferenceHelper::SnrPer CalculatePlcpHeaderSnrPer (Ptr<InterferenceHelper::Event> event) const;
/**
* Notify that RX has started.
@@ -212,47 +213,39 @@ public:
/**
* Create a NiChange at the given time and the amount of NI change.
*
* \param time time of the event
* \param delta the power
* \param power the power
* \param event causes this NI change
*/
NiChange (Time time, double delta, Ptr<InterferenceHelper::Event> event);
/**
* Return the event time.
*
* \return the event time.
*/
Time GetTime (void) const;
NiChange (double power, Ptr<InterferenceHelper::Event> event);
/**
* Return the power
*
* \return the power
*/
double GetDelta (void) const;
double GetPower (void) const;
/**
* Add a given amount of power.
*
* \param power the power to be added to the existing value
*/
void AddPower (double power);
/**
* 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).
*
* \param o
* \return true if a < o.time, false otherwise
*/
bool operator < (const NiChange& o) const;
private:
Time m_time; ///< time
double m_delta; ///< delta
double m_power; ///< power
Ptr<InterferenceHelper::Event> m_event; ///< event
};
/**
* typedef for a vector of NiChanges
* typedef for a multimap of NiChanges
*/
typedef std::vector <NiChange> NiChanges;
typedef std::multimap<Time, NiChange> NiChanges;
/**
* Append the given Event.
@@ -322,18 +315,36 @@ private:
bool m_rxing; ///< flag whether it is in receiving state
/**
* Returns a const iterator to the first nichange, which is later than moment
* Returns an iterator to the first nichange that is later than moment
*
* \param moment time to check from
* \returns an iterator to the list of NiChanges
*/
NiChanges::const_iterator GetPosition (Time moment);
NiChanges::const_iterator GetNextPosition (Time moment) const;
/**
* Add NiChange to the list at the appropriate position.
* Returns an iterator to the first nichange that is later than moment
*
* \param change
* \param moment time to check from
* \returns an iterator to the list of NiChanges
*/
void AddNiChangeEvent (NiChange change);
//NiChanges::iterator GetNextPosition (Time moment);
/**
* Returns an iterator to the last nichange that is before than moment
*
* \param moment time to check from
* \returns an iterator to the list of NiChanges
*/
NiChanges::const_iterator GetPreviousPosition (Time moment) const;
/**
* Add NiChange to the list at the appropriate position and
* return the iterator of the new event.
*
* \param moment
* \param change
* \returns the iterator of the new event
*/
NiChanges::iterator AddNiChangeEvent (Time moment, NiChange change);
};
} //namespace ns3