From 7d7bf0e0f85f07534afa555c6c320bf0c63cf5c4 Mon Sep 17 00:00:00 2001 From: Sebastien Deronne Date: Sat, 11 Apr 2020 14:32:25 +0200 Subject: [PATCH] wifi: Rework InterferenceHelper to handle calculations per [band start index; band stop index] pair --- .../model/wifi-spectrum-value-helper.cc | 68 ++--- .../model/wifi-spectrum-value-helper.h | 23 +- src/wifi/helper/wifi-helper.cc | 3 + src/wifi/model/interference-helper.cc | 288 ++++++++++++------ src/wifi/model/interference-helper.h | 139 ++++++--- src/wifi/model/spectrum-wifi-phy.cc | 111 ++++++- src/wifi/model/spectrum-wifi-phy.h | 17 +- src/wifi/model/wifi-phy-header.cc | 9 +- src/wifi/model/wifi-phy.cc | 108 ++++--- src/wifi/model/wifi-phy.h | 45 +-- src/wifi/model/wifi-tx-vector.cc | 5 + src/wifi/model/yans-wifi-channel.cc | 4 +- src/wifi/model/yans-wifi-phy.cc | 5 + src/wifi/test/inter-bss-test-suite.cc | 2 +- src/wifi/test/wifi-transmit-mask-test.cc | 2 +- 15 files changed, 561 insertions(+), 268 deletions(-) diff --git a/src/spectrum/model/wifi-spectrum-value-helper.cc b/src/spectrum/model/wifi-spectrum-value-helper.cc index 1c18402e8..904174d5d 100644 --- a/src/spectrum/model/wifi-spectrum-value-helper.cc +++ b/src/spectrum/model/wifi-spectrum-value-helper.cc @@ -197,10 +197,10 @@ WifiSpectrumValueHelper::CreateOfdmTxPowerSpectralDensity (uint32_t centerFreque uint32_t stop2 = start2 + 26 - 1; //Build transmit spectrum mask - std::vector subBands; + std::vector subBands; subBands.push_back (std::make_pair (start1, stop1)); subBands.push_back (std::make_pair (start2, stop2)); - StartStop maskBand (0, nAllocatedBands + nGuardBands); + WifiSpectrumBand maskBand (0, nAllocatedBands + nGuardBands); CreateSpectrumMaskForOfdm (c, subBands, maskBand, txPowerPerBandW, nGuardBands, innerSlopeWidth, -40.0); // -40 dBr for the outermost points of the standard defined mask for 11a, 11g and downclocked versions of 11a for 11p @@ -260,8 +260,8 @@ WifiSpectrumValueHelper::CreateHtOfdmTxPowerSpectralDensity (uint32_t centerFreq double lowestPointDbr = (centerFrequency >= 5000) ? -40.0 : //if 5 GHz band -45.0; //if 2.4 GHz band - std::vector subBands; //list of data/pilot-containing subBands (sent at 0dBr) - StartStop maskBand (0, nAllocatedBands + nGuardBands); + std::vector subBands; //list of data/pilot-containing subBands (sent at 0dBr) + WifiSpectrumBand maskBand (0, nAllocatedBands + nGuardBands); switch (channelWidth) { case 20: @@ -349,8 +349,8 @@ WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (uint32_t centerFreq double lowestPointDbr = (centerFrequency >= 5000) ? -40.0 : //if 5 GHz band -45.0; //if 2.4 GHz band - std::vector subBands; //list of data/pilot-containing subBands (sent at 0dBr) - StartStop maskBand (0, nAllocatedBands + nGuardBands); + std::vector subBands; //list of data/pilot-containing subBands (sent at 0dBr) + WifiSpectrumBand maskBand (0, nAllocatedBands + nGuardBands); switch (channelWidth) { case 20: @@ -449,34 +449,26 @@ WifiSpectrumValueHelper::CreateNoisePowerSpectralDensity (double noiseFigureDb, } Ptr -WifiSpectrumValueHelper::CreateRfFilter (uint32_t centerFrequency, uint16_t channelWidth, uint32_t bandBandwidth, uint16_t guardBandwidth) +WifiSpectrumValueHelper::CreateRfFilter (uint32_t centerFrequency, uint16_t totalChannelWidth, uint32_t bandBandwidth, uint16_t guardBandwidth, WifiSpectrumBand band) { - NS_LOG_FUNCTION (centerFrequency << channelWidth << bandBandwidth << guardBandwidth); - Ptr c = Create (GetSpectrumModel (centerFrequency, channelWidth, bandBandwidth, guardBandwidth)); - size_t numBands = c->GetSpectrumModel ()->GetNumBands (); + uint32_t startIndex = band.first; + uint32_t stopIndex = band.second; + NS_LOG_FUNCTION (centerFrequency << totalChannelWidth << bandBandwidth << guardBandwidth << startIndex << stopIndex); + Ptr c = Create (GetSpectrumModel (centerFrequency, totalChannelWidth, bandBandwidth, guardBandwidth)); Bands::const_iterator bit = c->ConstBandsBegin (); Values::iterator vit = c->ValuesBegin (); - size_t numBandsInFilter = static_cast (channelWidth * 1e6 / bandBandwidth); - if (channelWidth % bandBandwidth != 0) - { - numBandsInFilter += 1; - } - NS_LOG_INFO ("Num bands in filter: " << numBandsInFilter); - // Set the value of the filter to 1 for the center-most numBandsInFilter - NS_ASSERT_MSG ((numBandsInFilter % 2 == 1) && (numBands % 2 == 1), "Should have odd number of bands"); - size_t startIndex = (numBands - numBandsInFilter) / 2; vit += startIndex; bit += startIndex; - for (size_t i = startIndex; i < startIndex + numBandsInFilter; i++, vit++, bit++) + for (size_t i = startIndex; i <= stopIndex; i++, vit++, bit++) { *vit = 1; } - NS_LOG_LOGIC ("Added subbands " << startIndex << " to " << startIndex + numBandsInFilter << " to filter"); + NS_LOG_LOGIC ("Added subbands " << startIndex << " to " << stopIndex << " to filter"); return c; } void -WifiSpectrumValueHelper::CreateSpectrumMaskForOfdm (Ptr c, std::vector allocatedSubBands, StartStop maskBand, +WifiSpectrumValueHelper::CreateSpectrumMaskForOfdm (Ptr c, std::vector allocatedSubBands, WifiSpectrumBand maskBand, double txPowerPerBandW, uint32_t nGuardBands, uint32_t innerSlopeWidth, double lowestPointDbr) { @@ -496,22 +488,22 @@ WifiSpectrumValueHelper::CreateSpectrumMaskForOfdm (Ptr c, std::v //Different widths (in number of bands) uint32_t outerSlopeWidth = nGuardBands / 4; // nGuardBands is the total left+right guard band. The left/right outer part is half of the left/right guard band. uint32_t middleSlopeWidth = outerSlopeWidth - (innerSlopeWidth / 2); - StartStop outerBandLeft (maskBand.first, //to handle cases where allocated channel is under WifiPhy configured channel width. - maskBand.first + outerSlopeWidth - 1); - StartStop middleBandLeft (outerBandLeft.second + 1, - outerBandLeft.second + middleSlopeWidth); - StartStop innerBandLeft (allocatedSubBands.front ().first - innerSlopeWidth, - allocatedSubBands.front ().first - 1); //better to place slope based on allocated subcarriers - StartStop flatJunctionLeft (middleBandLeft.second + 1, - innerBandLeft.first - 1); //in order to handle shift due to guard subcarriers - StartStop outerBandRight (maskBand.second - outerSlopeWidth + 1, - maskBand.second); //start from outer edge to be able to compute flat junction width - StartStop middleBandRight (outerBandRight.first - middleSlopeWidth, - outerBandRight.first - 1); - StartStop innerBandRight (allocatedSubBands.back ().second + 1, - allocatedSubBands.back ().second + innerSlopeWidth); - StartStop flatJunctionRight (innerBandRight.second + 1, - middleBandRight.first - 1); + WifiSpectrumBand outerBandLeft (maskBand.first, //to handle cases where allocated channel is under WifiPhy configured channel width. + maskBand.first + outerSlopeWidth - 1); + WifiSpectrumBand middleBandLeft (outerBandLeft.second + 1, + outerBandLeft.second + middleSlopeWidth); + WifiSpectrumBand innerBandLeft (allocatedSubBands.front ().first - innerSlopeWidth, + allocatedSubBands.front ().first - 1); //better to place slope based on allocated subcarriers + WifiSpectrumBand flatJunctionLeft (middleBandLeft.second + 1, + innerBandLeft.first - 1); //in order to handle shift due to guard subcarriers + WifiSpectrumBand outerBandRight (maskBand.second - outerSlopeWidth + 1, + maskBand.second); //start from outer edge to be able to compute flat junction width + WifiSpectrumBand middleBandRight (outerBandRight.first - middleSlopeWidth, + outerBandRight.first - 1); + WifiSpectrumBand innerBandRight (allocatedSubBands.back ().second + 1, + allocatedSubBands.back ().second + innerSlopeWidth); + WifiSpectrumBand flatJunctionRight (innerBandRight.second + 1, + middleBandRight.first - 1); NS_LOG_DEBUG ("outerBandLeft=[" << outerBandLeft.first << ";" << outerBandLeft.second << "] " << "middleBandLeft=[" << middleBandLeft.first << ";" << middleBandLeft.second << "] " << "flatJunctionLeft=[" << flatJunctionLeft.first << ";" << flatJunctionLeft.second << "] " << diff --git a/src/spectrum/model/wifi-spectrum-value-helper.h b/src/spectrum/model/wifi-spectrum-value-helper.h index 3d26ccdcf..9f0417d49 100644 --- a/src/spectrum/model/wifi-spectrum-value-helper.h +++ b/src/spectrum/model/wifi-spectrum-value-helper.h @@ -28,6 +28,11 @@ namespace ns3 { +/** + * typedef for a pair of start and stop sub-band indexes + */ +typedef std::pair WifiSpectrumBand; + /** * \ingroup spectrum * @@ -137,20 +142,16 @@ public: /** * Create a spectral density corresponding to the RF filter * - * \param centerFrequency center frequency (MHz) - * \param channelWidth channel width (MHz) - * \param bandBandwidth width of each band (Hz) - * \param guardBandwidth width of the guard band (MHz) + * \param centerFrequency the center frequency (MHz) + * \param totalChannelWidth the total channel width (MHz) + * \param bandBandwidth the width of each band (MHz) + * \param guardBandwidth the width of the guard band (MHz) + * \param band the pair of start and stop indexes that defines the band to be filtered * * \return a pointer to a SpectrumValue representing the RF filter applied * to an received power spectral density */ - static Ptr CreateRfFilter (uint32_t centerFrequency, uint16_t channelWidth, uint32_t bandBandwidth, uint16_t guardBandwidth); - - /** - * typedef for a pair of start and stop sub-band indexes - */ - typedef std::pair StartStop; + static Ptr CreateRfFilter (uint32_t centerFrequency, uint16_t totalChannelWidth, uint32_t bandBandwidth, uint16_t guardBandwidth, WifiSpectrumBand band); /** * Create a transmit power spectral density corresponding to OFDM @@ -187,7 +188,7 @@ public: * \param lowestPointDbr maximum relative power of the outermost subcarriers of the guard band (in dBr) * \return a pointer to a newly allocated SpectrumValue representing the HT OFDM Transmit Power Spectral Density in W/Hz for each Band */ - static void CreateSpectrumMaskForOfdm (Ptr c, std::vector allocatedSubBands, StartStop maskBand, + static void CreateSpectrumMaskForOfdm (Ptr c, std::vector allocatedSubBands, WifiSpectrumBand maskBand, double txPowerPerBandW, uint32_t nGuardBands, uint32_t innerSlopeWidth, double lowestPointDbr); diff --git a/src/wifi/helper/wifi-helper.cc b/src/wifi/helper/wifi-helper.cc index 6431d2d1c..1f06a3fd5 100644 --- a/src/wifi/helper/wifi-helper.cc +++ b/src/wifi/helper/wifi-helper.cc @@ -981,6 +981,9 @@ WifiHelper::EnableLogComponents (void) LogComponentEnable ("YansErrorRateModel", LOG_LEVEL_ALL); LogComponentEnable ("YansWifiChannel", LOG_LEVEL_ALL); LogComponentEnable ("YansWifiPhy", LOG_LEVEL_ALL); + + //From Spectrum + LogComponentEnable ("WifiSpectrumValueHelper", LOG_LEVEL_ALL); } int64_t diff --git a/src/wifi/model/interference-helper.cc b/src/wifi/model/interference-helper.cc index 9b2641439..baecf6a80 100644 --- a/src/wifi/model/interference-helper.cc +++ b/src/wifi/model/interference-helper.cc @@ -19,6 +19,8 @@ * Sébastien Deronne */ +#include +#include #include "ns3/simulator.h" #include "ns3/log.h" #include "ns3/packet.h" @@ -37,7 +39,7 @@ NS_LOG_COMPONENT_DEFINE ("InterferenceHelper"); * PHY event class ****************************************************************/ -Event::Event (Ptr ppdu, WifiTxVector txVector, Time duration, double rxPower) +Event::Event (Ptr ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPower) : m_ppdu (ppdu), m_txVector (txVector), m_startTime (Simulator::Now ()), @@ -76,6 +78,26 @@ Event::GetDuration (void) const double Event::GetRxPowerW (void) const +{ + NS_ASSERT (m_rxPowerW.size () > 0); + //The total RX power corresponds to the maximum over all the bands + auto it = std::max_element (m_rxPowerW.begin (), m_rxPowerW.end (), + [] (const std::pair& p1, const std::pair& p2) { + return p1.second < p2.second; + }); + return it->second; +} + +double +Event::GetRxPowerW (WifiSpectrumBand band) const +{ + auto it = m_rxPowerW.find (band); + NS_ASSERT (it != m_rxPowerW.end ()); + return it->second; +} + +RxPowerWattPerChannelBand +Event::GetRxPowerWPerBand (void) const { return m_rxPowerW; } @@ -132,11 +154,8 @@ InterferenceHelper::NiChange::GetEvent (void) const InterferenceHelper::InterferenceHelper () : m_errorRateModel (0), m_numRxAntennas (1), - 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 () @@ -146,7 +165,7 @@ InterferenceHelper::~InterferenceHelper () } Ptr -InterferenceHelper::Add (Ptr ppdu, WifiTxVector txVector, Time duration, double rxPowerW) +InterferenceHelper::Add (Ptr ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPowerW) { Ptr event = Create (ppdu, txVector, duration, rxPowerW); AppendEvent (event); @@ -154,7 +173,7 @@ InterferenceHelper::Add (Ptr ppdu, WifiTxVector txVector, Time d } void -InterferenceHelper::AddForeignSignal (Time duration, double rxPowerW) +InterferenceHelper::AddForeignSignal (Time duration, RxPowerWattPerChannelBand rxPowerW) { // Parameters other than duration and rxPowerW are unused for this type // of signal, so we provide dummy versions @@ -165,6 +184,26 @@ InterferenceHelper::AddForeignSignal (Time duration, double rxPowerW) Add (fakePpdu, WifiTxVector (), duration, rxPowerW); } +void +InterferenceHelper::RemoveBands(void) +{ + NS_LOG_FUNCTION (this); + m_niChangesPerBand.clear(); + m_firstPowerPerBand.clear(); +} + +void +InterferenceHelper::AddBand (WifiSpectrumBand band) +{ + NS_LOG_FUNCTION (this << band.first << band.second); + NS_ASSERT (m_niChangesPerBand.find (band) == m_niChangesPerBand.end ()); + NiChanges niChanges; + m_niChangesPerBand.insert ({band, niChanges}); + // Always have a zero power noise event in the list + AddNiChangeEvent (Time (0), NiChange (0.0, 0), band); + m_firstPowerPerBand.insert ({band, 0.0}); +} + void InterferenceHelper::SetNoiseFigure (double value) { @@ -190,12 +229,14 @@ InterferenceHelper::SetNumberOfReceiveAntennas (uint8_t rx) } Time -InterferenceHelper::GetEnergyDuration (double energyW) const +InterferenceHelper::GetEnergyDuration (double energyW, WifiSpectrumBand band) const { Time now = Simulator::Now (); - auto i = GetPreviousPosition (now); + auto i = GetPreviousPosition (now, band); Time end = i->first; - for (; i != m_niChanges.end (); ++i) + auto ni_it = m_niChangesPerBand.find (band); + NS_ASSERT (ni_it != m_niChangesPerBand.end ()); + for (; i != ni_it->second.end (); ++i) { double noiseInterferenceW = i->second.GetPower (); end = i->first; @@ -211,29 +252,35 @@ void InterferenceHelper::AppendEvent (Ptr event) { 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) + RxPowerWattPerChannelBand rxPowerWattPerChannelBand = event->GetRxPowerWPerBand (); + for (auto const& it : rxPowerWattPerChannelBand) { - 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 ()); + WifiSpectrumBand band = it.first; + auto ni_it = m_niChangesPerBand.find (band); + NS_ASSERT (ni_it != m_niChangesPerBand.end ()); + double previousPowerStart = 0; + double previousPowerEnd = 0; + previousPowerStart = GetPreviousPosition (event->GetStartTime (), band)->second.GetPower (); + previousPowerEnd = GetPreviousPosition (event->GetEndTime (), band)->second.GetPower (); + if (!m_rxing) + { + m_firstPowerPerBand.find (band)->second = previousPowerStart; + // Always leave the first zero power noise event in the list + ni_it->second.erase (++(ni_it->second.begin ()), GetNextPosition (event->GetStartTime (), band)); + } + auto first = AddNiChangeEvent (event->GetStartTime (), NiChange (previousPowerStart, event), band); + auto last = AddNiChangeEvent (event->GetEndTime (), NiChange (previousPowerEnd, event), band); + for (auto i = first; i != last; ++i) + { + i->second.AddPower (it.second); + } } } double InterferenceHelper::CalculateSnr (double signal, double noiseInterference, uint16_t channelWidth, uint8_t nss) const { + NS_LOG_FUNCTION (this << signal << noiseInterference << channelWidth << +nss); //thermal noise at 290K in J/s = W static const double BOLTZMANN = 1.3803e-23; //Nt is the power of thermal noise in W @@ -254,22 +301,30 @@ InterferenceHelper::CalculateSnr (double signal, double noiseInterference, uint1 } double -InterferenceHelper::CalculateNoiseInterferenceW (Ptr event, NiChanges *ni) const +InterferenceHelper::CalculateNoiseInterferenceW (Ptr event, NiChangesPerBand *nis, WifiSpectrumBand band) const { - double noiseInterferenceW = m_firstPower; - auto it = m_niChanges.find (event->GetStartTime ()); - for (; it != m_niChanges.end () && it->first < Simulator::Now (); ++it) + NS_LOG_FUNCTION (this << band.first << band.second); + auto firstPower_it = m_firstPowerPerBand.find (band); + NS_ASSERT (firstPower_it != m_firstPowerPerBand.end ()); + double noiseInterferenceW = firstPower_it->second; + auto ni_it = m_niChangesPerBand.find (band); + NS_ASSERT (ni_it != m_niChangesPerBand.end ()); + auto it = ni_it->second.find (event->GetStartTime ()); + for (; it != ni_it->second.end () && it->first < Simulator::Now (); ++it) { - noiseInterferenceW = it->second.GetPower () - event->GetRxPowerW (); + noiseInterferenceW = it->second.GetPower () - event->GetRxPowerW (band); } - 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) + it = ni_it->second.find (event->GetStartTime ()); + NS_ASSERT (it != ni_it->second.end ()); + for (; it != ni_it->second.end () && it->second.GetEvent () != event; ++it); + NiChanges ni; + ni.emplace (event->GetStartTime (), NiChange (0, event)); + while (++it != ni_it->second.end () && it->second.GetEvent () != event) { - ni->insert (*it); + ni.insert (*it); } - ni->emplace (event->GetEndTime (), NiChange (0, event)); + ni.emplace (event->GetEndTime (), NiChange (0, event)); + nis->insert ({band, ni}); NS_ASSERT_MSG (noiseInterferenceW >= 0, "CalculateNoiseInterferenceW returns negative value " << noiseInterferenceW); return noiseInterferenceW; } @@ -303,30 +358,31 @@ InterferenceHelper::CalculatePayloadChunkSuccessRate (double snir, Time duration } double -InterferenceHelper::CalculatePayloadPer (Ptr event, uint16_t staId, - NiChanges *ni, std::pair window) const +InterferenceHelper::CalculatePayloadPer (Ptr event, NiChangesPerBand *nis, WifiSpectrumBand band, + uint16_t staId, std::pair window) const { - NS_LOG_FUNCTION (this << staId << window.first << window.second); + NS_LOG_FUNCTION (this << band.first << band.second << staId << window.first << window.second); const WifiTxVector txVector = event->GetTxVector (); double psr = 1.0; /* Packet Success Rate */ - auto j = ni->begin (); + auto ni_it = nis->find (band)->second; + auto j = ni_it.begin (); Time previous = j->first; WifiMode payloadMode = txVector.GetMode (staId); WifiPreamble preamble = txVector.GetPreambleType (); Time phyHeaderStart = j->first + WifiPhy::GetPhyPreambleDuration (txVector); //PPDU start time + preamble - Time phyLSigHeaderEnd = phyHeaderStart + WifiPhy::GetPhyHeaderDuration (txVector); //PPDU start time + preamble + L-SIG - Time phyTrainingSymbolsStart = phyLSigHeaderEnd + WifiPhy::GetPhyHtSigHeaderDuration (preamble) + WifiPhy::GetPhySigA1Duration (preamble) + WifiPhy::GetPhySigA2Duration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A + Time phyHtSigHeaderStart = phyHeaderStart + WifiPhy::GetPhyHeaderDuration (txVector); //PPDU start time + preamble + L-SIG + Time phyTrainingSymbolsStart = phyHtSigHeaderStart + WifiPhy::GetPhyHtSigHeaderDuration (preamble) + WifiPhy::GetPhySigA1Duration (preamble) + WifiPhy::GetPhySigA2Duration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A Time phyPayloadStart = phyTrainingSymbolsStart + WifiPhy::GetPhyTrainingSymbolDuration (txVector) + WifiPhy::GetPhySigBDuration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B Time windowStart = phyPayloadStart + window.first; Time windowEnd = phyPayloadStart + window.second; - double noiseInterferenceW = m_firstPower; - double powerW = event->GetRxPowerW (); - while (++j != ni->end ()) + double noiseInterferenceW = m_firstPowerPerBand.find (band)->second; + double powerW = event->GetRxPowerW (band); + while (++j != ni_it.end ()) { Time current = j->first; NS_LOG_DEBUG ("previous= " << previous << ", current=" << current); NS_ASSERT (current >= previous); - double snr = CalculateSnr (powerW, noiseInterferenceW, txVector.GetChannelWidth (), txVector.GetNss (staId)); + double snr = CalculateSnr (powerW, noiseInterferenceW, channelWidth, txVector.GetNss (staId)); //Case 1: Both previous and current point to the windowed payload if (previous >= windowStart) { @@ -352,12 +408,14 @@ InterferenceHelper::CalculatePayloadPer (Ptr event, uint16_t staId, } double -InterferenceHelper::CalculateNonHtPhyHeaderPer (Ptr event, NiChanges *ni) const +InterferenceHelper::CalculateNonHtPhyHeaderPer (Ptr event, NiChangesPerBand *nis, WifiSpectrumBand band) const { - NS_LOG_FUNCTION (this); + NS_LOG_FUNCTION (this << band.first << band.second); const WifiTxVector txVector = event->GetTxVector (); + uint16_t channelWidth = txVector.GetChannelWidth () >= 40 ? 20 : txVector.GetChannelWidth (); //calculate PER on the 20 MHz primary channel for L-SIG double psr = 1.0; /* Packet Success Rate */ - auto j = ni->begin (); + auto ni_it = nis->find (band)->second; + auto j = ni_it.begin (); Time previous = j->first; WifiPreamble preamble = txVector.GetPreambleType (); WifiMode headerMode = WifiPhy::GetPhyHeaderMode (txVector); @@ -365,14 +423,14 @@ InterferenceHelper::CalculateNonHtPhyHeaderPer (Ptr event, NiChange Time phyLSigHeaderEnd = phyHeaderStart + WifiPhy::GetPhyHeaderDuration (txVector); //PPDU start time + preamble + L-SIG Time phyTrainingSymbolsStart = phyLSigHeaderEnd + WifiPhy::GetPhyHtSigHeaderDuration (preamble) + WifiPhy::GetPhySigA1Duration (preamble) + WifiPhy::GetPhySigA2Duration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A Time phyPayloadStart = phyTrainingSymbolsStart + WifiPhy::GetPhyTrainingSymbolDuration (txVector) + WifiPhy::GetPhySigBDuration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B - double noiseInterferenceW = m_firstPower; - double powerW = event->GetRxPowerW (); - while (++j != ni->end ()) + double noiseInterferenceW = m_firstPowerPerBand.find (band)->second; + double powerW = event->GetRxPowerW (band); + while (++j != ni_it.end ()) { Time current = j->first; NS_LOG_DEBUG ("previous= " << previous << ", current=" << current); NS_ASSERT (current >= previous); - double snr = CalculateSnr (powerW, noiseInterferenceW, txVector.GetChannelWidth (), 1); + double snr = CalculateSnr (powerW, noiseInterferenceW, channelWidth, 1); //Case 1: previous and current after payload start if (previous >= phyPayloadStart) { @@ -465,12 +523,14 @@ InterferenceHelper::CalculateNonHtPhyHeaderPer (Ptr event, NiChange } double -InterferenceHelper::CalculateHtPhyHeaderPer (Ptr event, NiChanges *ni) const +InterferenceHelper::CalculateHtPhyHeaderPer (Ptr event, NiChangesPerBand *nis, WifiSpectrumBand band) const { - NS_LOG_FUNCTION (this); + NS_LOG_FUNCTION (this << band.first << band.second); const WifiTxVector txVector = event->GetTxVector (); + uint16_t channelWidth = txVector.GetChannelWidth () >= 40 ? 20 : txVector.GetChannelWidth (); //calculate PER on the 20 MHz primary channel for PHY headers double psr = 1.0; /* Packet Success Rate */ - auto j = ni->begin (); + auto ni_it = nis->find (band)->second; + auto j = ni_it.begin (); Time previous = j->first; WifiPreamble preamble = txVector.GetPreambleType (); WifiMode mcsHeaderMode; @@ -494,14 +554,14 @@ InterferenceHelper::CalculateHtPhyHeaderPer (Ptr event, NiChanges * Time phyLSigHeaderEnd = phyHeaderStart + WifiPhy::GetPhyHeaderDuration (txVector); //PPDU start time + preamble + L-SIG Time phyTrainingSymbolsStart = phyLSigHeaderEnd + WifiPhy::GetPhyHtSigHeaderDuration (preamble) + WifiPhy::GetPhySigA1Duration (preamble) + WifiPhy::GetPhySigA2Duration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A Time phyPayloadStart = phyTrainingSymbolsStart + WifiPhy::GetPhyTrainingSymbolDuration (txVector) + WifiPhy::GetPhySigBDuration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B - double noiseInterferenceW = m_firstPower; - double powerW = event->GetRxPowerW (); - while (++j != ni->end ()) + double noiseInterferenceW = m_firstPowerPerBand.find (band)->second; + double powerW = event->GetRxPowerW (band); + while (++j != ni_it.end ()) { Time current = j->first; NS_LOG_DEBUG ("previous= " << previous << ", current=" << current); NS_ASSERT (current >= previous); - double snr = CalculateSnr (powerW, noiseInterferenceW, txVector.GetChannelWidth (), 1); + double snr = CalculateSnr (powerW, noiseInterferenceW, channelWidth, 1); //Case 1: previous and current after payload start: nothing to do if (previous >= phyPayloadStart) { @@ -731,20 +791,21 @@ InterferenceHelper::CalculateHtPhyHeaderPer (Ptr event, NiChanges * } struct InterferenceHelper::SnrPer -InterferenceHelper::CalculatePayloadSnrPer (Ptr event, uint16_t staId, - std::pair relativeMpduStartStop) const +InterferenceHelper::CalculatePayloadSnrPer (Ptr event, uint16_t channelWidth, WifiSpectrumBand band, + uint16_t staId, std::pair relativeMpduStartStop) const { - NiChanges ni; - double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni); - double snr = CalculateSnr (event->GetRxPowerW (), + NS_LOG_FUNCTION (this << channelWidth << band.first << band.second << staId << relativeMpduStartStop.first << relativeMpduStartStop.second); + NiChangesPerBand ni; + double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band); + double snr = CalculateSnr (event->GetRxPowerW (band), noiseInterferenceW, - event->GetTxVector ().GetChannelWidth (), + channelWidth, event->GetTxVector ().GetNss (staId)); /* calculate the SNIR at the start of the MPDU (located through windowing) and accumulate * all SNIR changes in the SNIR vector. */ - double per = CalculatePayloadPer (event, staId, &ni, relativeMpduStartStop); + double per = CalculatePayloadPer (event, &ni, band, staId, relativeMpduStartStop); struct SnrPer snrPer; snrPer.snr = snr; @@ -753,31 +814,41 @@ InterferenceHelper::CalculatePayloadSnrPer (Ptr event, uint16_t staId, } double -InterferenceHelper::CalculateSnr (Ptr event, uint8_t nss) const +InterferenceHelper::CalculateSnr (Ptr event, uint16_t channelWidth, uint8_t nss, WifiSpectrumBand band) const { - NiChanges ni; - double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni); - double snr = CalculateSnr (event->GetRxPowerW (), + NiChangesPerBand ni; + double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band); + double snr = CalculateSnr (event->GetRxPowerW (band), noiseInterferenceW, - event->GetTxVector ().GetChannelWidth (), + channelWidth, nss); - return snr; + return snr; } struct InterferenceHelper::SnrPer -InterferenceHelper::CalculateNonHtPhyHeaderSnrPer (Ptr event) const +InterferenceHelper::CalculateNonHtPhyHeaderSnrPer (Ptr event, WifiSpectrumBand band) const { - NiChanges ni; - double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni); - double snr = CalculateSnr (event->GetRxPowerW (), + NS_LOG_FUNCTION (this << band.first << band.second); + NiChangesPerBand ni; + uint16_t channelWidth; + if (event->GetTxVector ().GetChannelWidth () >= 40) + { + channelWidth = 20; //calculate PER on the 20 MHz primary channel for L-SIG + } + else + { + channelWidth = event->GetTxVector ().GetChannelWidth (); + } + double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band); + double snr = CalculateSnr (event->GetRxPowerW (band), noiseInterferenceW, - event->GetTxVector ().GetChannelWidth (), + channelWidth, 1); /* calculate the SNIR at the start of the PHY header and accumulate * all SNIR changes in the SNIR vector. */ - double per = CalculateNonHtPhyHeaderPer (event, &ni); + double per = CalculateNonHtPhyHeaderPer (event, &ni, band); struct SnrPer snrPer; snrPer.snr = snr; @@ -786,19 +857,29 @@ InterferenceHelper::CalculateNonHtPhyHeaderSnrPer (Ptr event) const } struct InterferenceHelper::SnrPer -InterferenceHelper::CalculateHtPhyHeaderSnrPer (Ptr event) const +InterferenceHelper::CalculateHtPhyHeaderSnrPer (Ptr event, WifiSpectrumBand band) const { - NiChanges ni; - double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni); - double snr = CalculateSnr (event->GetRxPowerW (), + NS_LOG_FUNCTION (this << band.first << band.second); + NiChangesPerBand ni; + uint16_t channelWidth; + if (event->GetTxVector ().GetChannelWidth () >= 40) + { + channelWidth = 20; //calculate PER on the 20 MHz primary channel for PHY headers + } + else + { + channelWidth = event->GetTxVector ().GetChannelWidth (); + } + double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band); + double snr = CalculateSnr (event->GetRxPowerW (band), noiseInterferenceW, - event->GetTxVector ().GetChannelWidth (), + channelWidth, 1); /* calculate the SNIR at the start of the PHY header and accumulate * all SNIR changes in the SNIR vector. */ - double per = CalculateHtPhyHeaderPer (event, &ni); + double per = CalculateHtPhyHeaderPer (event, &ni, band); struct SnrPer snrPer; snrPer.snr = snr; @@ -809,23 +890,28 @@ InterferenceHelper::CalculateHtPhyHeaderSnrPer (Ptr event) const void InterferenceHelper::EraseEvents (void) { - m_niChanges.clear (); - // Always have a zero power noise event in the list - AddNiChangeEvent (Time (0), NiChange (0.0, 0)); + for (auto it : m_niChangesPerBand) + { + it.second.clear (); + // Always have a zero power noise event in the list + AddNiChangeEvent (Time (0), NiChange (0.0, 0), it.first); + m_firstPowerPerBand.at (it.first) = 0.0; + } m_rxing = false; - m_firstPower = 0; } InterferenceHelper::NiChanges::const_iterator -InterferenceHelper::GetNextPosition (Time moment) const +InterferenceHelper::GetNextPosition (Time moment, WifiSpectrumBand band) const { - return m_niChanges.upper_bound (moment); + auto it = m_niChangesPerBand.find (band); + NS_ASSERT (it != m_niChangesPerBand.end ()); + return it->second.upper_bound (moment); } InterferenceHelper::NiChanges::const_iterator -InterferenceHelper::GetPreviousPosition (Time moment) const +InterferenceHelper::GetPreviousPosition (Time moment, WifiSpectrumBand band) const { - auto it = GetNextPosition (moment); + auto it = GetNextPosition (moment, band); // This is safe since there is always an NiChange at time 0, // before moment. --it; @@ -833,9 +919,11 @@ InterferenceHelper::GetPreviousPosition (Time moment) const } InterferenceHelper::NiChanges::iterator -InterferenceHelper::AddNiChangeEvent (Time moment, NiChange change) +InterferenceHelper::AddNiChangeEvent (Time moment, NiChange change, WifiSpectrumBand band) { - return m_niChanges.insert (GetNextPosition (moment), std::make_pair (moment, change)); + auto it = m_niChangesPerBand.find (band); + NS_ASSERT (it != m_niChangesPerBand.end ()); + return it->second.insert (GetNextPosition (moment, band), std::make_pair (moment, change)); } void @@ -851,9 +939,13 @@ InterferenceHelper::NotifyRxEnd () NS_LOG_FUNCTION (this); m_rxing = false; //Update m_firstPower for frame capture - auto it = GetPreviousPosition (Simulator::Now ()); - it--; - m_firstPower = it->second.GetPower (); + for (auto ni : m_niChangesPerBand) + { + NS_ASSERT (ni.second.size () > 1); + auto it = GetPreviousPosition (Simulator::Now (), ni.first); + it--; + m_firstPowerPerBand.find (ni.first)->second = it->second.GetPower (); + } } } //namespace ns3 diff --git a/src/wifi/model/interference-helper.h b/src/wifi/model/interference-helper.h index b1aab6089..9f41d97f9 100644 --- a/src/wifi/model/interference-helper.h +++ b/src/wifi/model/interference-helper.h @@ -22,6 +22,7 @@ #define INTERFERENCE_HELPER_H #include "ns3/nstime.h" +#include "ns3/wifi-spectrum-value-helper.h" #include "wifi-tx-vector.h" #include @@ -31,6 +32,11 @@ class WifiPpdu; class WifiPsdu; class ErrorRateModel; +/** + * A map of the received power (Watts) for each band + */ +typedef std::map RxPowerWattPerChannelBand; + /** * \ingroup wifi * \brief handles interference calculations @@ -45,9 +51,9 @@ public: * \param ppdu the PPDU * \param txVector the TXVECTOR * \param duration duration of the PPDU - * \param rxPower the received power (w) + * \param rxPower the received power per band (W) */ - Event (Ptr ppdu, WifiTxVector txVector, Time duration, double rxPower); + Event (Ptr ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPower); ~Event (); /** @@ -75,11 +81,24 @@ public: */ Time GetDuration (void) const; /** - * Return the received power (w). + * Return the total received power (W). * - * \return the received power (w) + * \return the total received power (W) */ double GetRxPowerW (void) const; + /** + * Return the received power (W) for a given band. + * + * \param band the band for which the power should be returned + * \return the received power (W) for a given band + */ + double GetRxPowerW (WifiSpectrumBand band) const; + /** + * Return the received power (W) for all bands. + * + * \return the received power (W) for all bands. + */ + RxPowerWattPerChannelBand GetRxPowerWPerBand (void) const; /** * Return the TXVECTOR of the PPDU. * @@ -89,11 +108,11 @@ public: private: - Ptr m_ppdu; ///< PPDU - WifiTxVector m_txVector; ///< TXVECTOR - Time m_startTime; ///< start time - Time m_endTime; ///< end time - double m_rxPowerW; ///< received power in watts + Ptr m_ppdu; //!< PPDU + WifiTxVector m_txVector; //!< TXVECTOR + Time m_startTime; //!< start time + Time m_endTime; //!< end time + RxPowerWattPerChannelBand m_rxPowerW; //!< received power in watts per band }; /** @@ -129,6 +148,18 @@ public: InterferenceHelper (); ~InterferenceHelper (); + /** + * Add a frequency band. + * + * \param band the band to be created + */ + void AddBand (WifiSpectrumBand band); + + /** + * Remove the frequency bands. + */ + void RemoveBands (void); + /** * Set the noise figure. * @@ -158,30 +189,32 @@ public: /** * \param energyW the minimum energy (W) requested + * \param band identify the requested band * * \returns the expected amount of time the observed - * energy on the medium will be higher than - * the requested threshold. + * energy on the medium for a given band will + * be higher than the requested threshold. */ - Time GetEnergyDuration (double energyW) const; + Time GetEnergyDuration (double energyW, WifiSpectrumBand band) const; /** * Add the PPDU-related signal to interference helper. * * \param ppdu the PPDU * \param txVector the TXVECTOR - * \param rxPower received power (W) + * \param duration the PPDU duration + * \param rxPower received power per band (W) * * \return Event */ - Ptr Add (Ptr ppdu, WifiTxVector txVector, Time duration, double rxPower); + Ptr Add (Ptr ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPower); /** * Add a non-Wifi signal to interference helper. * \param duration the duration of the signal - * \param rxPower received power (W) + * \param rxPower received power per band (W) */ - void AddForeignSignal (Time duration, double rxPower); + void AddForeignSignal (Time duration, RxPowerWattPerChannelBand rxPower); /** * Calculate the SNIR at the start of the payload and accumulate * all SNIR changes in the SNIR vector for each MPDU of an A-MPDU. @@ -190,40 +223,46 @@ public: * this class. * * \param event the event corresponding to the first time the corresponding PPDU arrives + * \param channelWidth the channel width used to transmit the PSDU (in MHz) + * \param band identify the band used by the PSDU * \param staId the station ID of the PSDU (only used for MU) * \param relativeMpduStartStop the time window (pair of start and end times) of PHY payload to focus on * * \return struct of SNR and PER (with PER being evaluated over the provided time window) */ - struct InterferenceHelper::SnrPer CalculatePayloadSnrPer (Ptr event, uint16_t staId, - std::pair relativeMpduStartStop) const; + struct InterferenceHelper::SnrPer CalculatePayloadSnrPer (Ptr event, uint16_t channelWidth, WifiSpectrumBand band, + uint16_t staId, std::pair relativeMpduStartStop) const; /** * Calculate the SNIR for the event (starting from now until the event end). * * \param event the event corresponding to the first time the corresponding PPDU arrives + * \param channelWidth the channel width (in MHz) * \param nss the number of spatial streams + * \param band identify the band used by the PSDU * * \return the SNR for the PPDU in linear scale */ - double CalculateSnr (Ptr event, uint8_t nss) const; + double CalculateSnr (Ptr event, uint16_t channelWidth, uint8_t nss, WifiSpectrumBand band) const; /** * Calculate the SNIR at the start of the non-HT PHY header and accumulate * all SNIR changes in the SNIR vector. * * \param event the event corresponding to the first time the corresponding PPDU arrives + * \param band identify the band used by the PSDU * * \return struct of SNR and PER */ - struct InterferenceHelper::SnrPer CalculateNonHtPhyHeaderSnrPer (Ptr event) const; + struct InterferenceHelper::SnrPer CalculateNonHtPhyHeaderSnrPer (Ptr event, WifiSpectrumBand band) const; /** * Calculate the SNIR at the start of the HT PHY header and accumulate * all SNIR changes in the SNIR vector. * * \param event the event corresponding to the first time the corresponding PPDU arrives + * \param band identify the band used by the PSDU * * \return struct of SNR and PER */ - struct InterferenceHelper::SnrPer CalculateHtPhyHeaderSnrPer (Ptr event) const; + struct InterferenceHelper::SnrPer CalculateHtPhyHeaderSnrPer (Ptr event, WifiSpectrumBand band) const; /** * Notify that RX has started. @@ -305,10 +344,15 @@ private: }; /** - * typedef for a multimap of NiChanges + * typedef for a multimap of NiChange */ typedef std::multimap NiChanges; + /** + * Map of NiChanges per band + */ + typedef std::map NiChangesPerBand; + /** * Append the given Event. * @@ -319,11 +363,12 @@ private: * Calculate noise and interference power in W. * * \param event the event - * \param ni the NiChanges + * \param nis the NiChanges + * \param band the band * * \return noise and interference power */ - double CalculateNoiseInterferenceW (Ptr event, NiChanges *ni) const; + double CalculateNoiseInterferenceW (Ptr event, NiChangesPerBand *nis, WifiSpectrumBand band) const; /** * Calculate the success rate of the payload chunk given the SINR, duration, and Wi-Fi mode. * The duration and mode are used to calculate how many bits are present in the chunk. @@ -342,64 +387,61 @@ private: * multiple chunks (e.g. due to interference from other transmissions). * * \param event the event + * \param nis the NiChanges + * \param band identify the band used by the PSDU * \param staId the station ID of the PSDU (only used for MU) - * \param ni the NiChanges * \param window time window (pair of start and end times) of PHY payload to focus on * * \return the error rate of the payload */ - double CalculatePayloadPer (Ptr event, uint16_t staId, - NiChanges *ni, std::pair window) const; + double CalculatePayloadPer (Ptr event, NiChangesPerBand *nis, WifiSpectrumBand band, + uint16_t staId, std::pair window) const; /** * Calculate the error rate of the non-HT PHY header. The non-HT PHY header * can be divided into multiple chunks (e.g. due to interference from other transmissions). * * \param event the event - * \param ni the NiChanges + * \param nis the NiChanges + * \param band the band * * \return the error rate of the non-HT PHY header */ - double CalculateNonHtPhyHeaderPer (Ptr event, NiChanges *ni) const; + double CalculateNonHtPhyHeaderPer (Ptr event, NiChangesPerBand *nis, WifiSpectrumBand band) const; /** * Calculate the error rate of the HT PHY header. TheHT PHY header * can be divided into multiple chunks (e.g. due to interference from other transmissions). * * \param event the event - * \param ni the NiChanges + * \param nis the NiChanges + * \param band the band * * \return the error rate of the HT PHY header */ - double CalculateHtPhyHeaderPer (Ptr event, NiChanges *ni) const; + double CalculateHtPhyHeaderPer (Ptr event, NiChangesPerBand *nis, WifiSpectrumBand band) const; - double m_noiseFigure; /**< noise figure (linear) */ - Ptr m_errorRateModel; ///< error rate model - uint8_t m_numRxAntennas; /**< the number of RX antennas in the corresponding receiver */ - /// Experimental: needed for energy duration calculation - NiChanges m_niChanges; - double m_firstPower; ///< first power in watts - bool m_rxing; ///< flag whether it is in receiving state + double m_noiseFigure; //!< noise figure (linear) + Ptr m_errorRateModel; //!< error rate model + uint8_t m_numRxAntennas; //!< the number of RX antennas in the corresponding receiver + NiChangesPerBand m_niChangesPerBand; //!< NI Changes for each band + std::map m_firstPowerPerBand; //!< first power of each band in watts + bool m_rxing; //!< flag whether it is in receiving state /** * Returns an iterator to the first NiChange that is later than moment * * \param moment time to check from + * \param band identify the band to check * \returns an iterator to the list of NiChanges */ - NiChanges::const_iterator GetNextPosition (Time moment) const; - /** - * 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::iterator GetNextPosition (Time moment); + NiChanges::const_iterator GetNextPosition (Time moment, WifiSpectrumBand band) const; /** * Returns an iterator to the last NiChange that is before than moment * * \param moment time to check from + * \param band identify the band to check * \returns an iterator to the list of NiChanges */ - NiChanges::const_iterator GetPreviousPosition (Time moment) const; + NiChanges::const_iterator GetPreviousPosition (Time moment, WifiSpectrumBand band) const; /** * Add NiChange to the list at the appropriate position and @@ -407,9 +449,10 @@ private: * * \param moment time to check from * \param change the NiChange to add + * \param band identify the band to check * \returns the iterator of the new event */ - NiChanges::iterator AddNiChangeEvent (Time moment, NiChange change); + NiChanges::iterator AddNiChangeEvent (Time moment, NiChange change, WifiSpectrumBand band); }; } //namespace ns3 diff --git a/src/wifi/model/spectrum-wifi-phy.cc b/src/wifi/model/spectrum-wifi-phy.cc index bb49621b1..3fd0716ff 100644 --- a/src/wifi/model/spectrum-wifi-phy.cc +++ b/src/wifi/model/spectrum-wifi-phy.cc @@ -23,7 +23,6 @@ * with Nicola Baldo and Dean Armstrong */ -#include "ns3/wifi-spectrum-value-helper.h" #include "ns3/log.h" #include "ns3/boolean.h" #include "ns3/net-device.h" @@ -96,7 +95,7 @@ SpectrumWifiPhy::DoInitialize (void) } Ptr -SpectrumWifiPhy::GetRxSpectrumModel () const +SpectrumWifiPhy::GetRxSpectrumModel () { NS_LOG_FUNCTION (this); if (m_rxSpectrumModel) @@ -115,11 +114,35 @@ SpectrumWifiPhy::GetRxSpectrumModel () const uint16_t channelWidth = GetChannelWidth (); NS_LOG_DEBUG ("Creating spectrum model from frequency/width pair of (" << GetFrequency () << ", " << channelWidth << ")"); m_rxSpectrumModel = WifiSpectrumValueHelper::GetSpectrumModel (GetFrequency (), channelWidth, GetBandBandwidth (), GetGuardBandwidth (channelWidth)); + UpdateInterferenceHelperBands (); } } return m_rxSpectrumModel; } +void +SpectrumWifiPhy::UpdateInterferenceHelperBands (void) +{ + NS_LOG_FUNCTION (this); + uint16_t channelWidth = GetChannelWidth (); + m_interference.RemoveBands (); + if (channelWidth < 20) + { + WifiSpectrumBand band = GetBand (channelWidth); + m_interference.AddBand (band); + } + else + { + for (uint16_t bw = 160; bw >= 20; bw = bw / 2) + { + for (uint8_t i = 0; i < (channelWidth / bw); ++i) + { + m_interference.AddBand (GetBand (bw, i)); + } + } + } +} + Ptr SpectrumWifiPhy::GetChannel (void) const { @@ -143,6 +166,7 @@ SpectrumWifiPhy::ResetSpectrumModel (void) // on the SpectrumChannel to provide this new spectrum model to it m_rxSpectrumModel = WifiSpectrumValueHelper::GetSpectrumModel (GetFrequency (), channelWidth, GetBandBandwidth (), GetGuardBandwidth (channelWidth)); m_channel->AddRx (m_wifiSpectrumPhyInterface); + UpdateInterferenceHelperBands (); } void @@ -202,27 +226,67 @@ SpectrumWifiPhy::StartRx (Ptr rxParams) senderNodeId = rxParams->txPhy->GetDevice ()->GetNode ()->GetId (); } NS_LOG_DEBUG ("Received signal from " << senderNodeId << " with unfiltered power " << WToDbm (Integral (*receivedSignalPsd)) << " dBm"); + // Integrate over our receive bandwidth (i.e., all that the receive // spectral mask representing our filtering allows) to find the // total energy apparent to the "demodulator". + // This is done per 20 MHz channel band. uint16_t channelWidth = GetChannelWidth (); - Ptr filter = WifiSpectrumValueHelper::CreateRfFilter (GetFrequency (), channelWidth, GetBandBandwidth (), GetGuardBandwidth (channelWidth)); - SpectrumValue filteredSignal = (*filter) * (*receivedSignalPsd); - // Add receiver antenna gain - NS_LOG_DEBUG ("Signal power received (watts) before antenna gain: " << Integral (filteredSignal)); - double rxPowerW = Integral (filteredSignal) * DbToRatio (GetRxGain ()); - NS_LOG_DEBUG ("Signal power received after antenna gain: " << rxPowerW << " W (" << WToDbm (rxPowerW) << " dBm)"); + double totalRxPowerW = 0; + RxPowerWattPerChannelBand rxPowerW; + + if ((channelWidth == 5) || (channelWidth == 10)) + { + WifiSpectrumBand filteredBand = GetBand (channelWidth); + Ptr filter = WifiSpectrumValueHelper::CreateRfFilter (GetFrequency (), channelWidth, GetBandBandwidth (), GetGuardBandwidth (channelWidth), filteredBand); + SpectrumValue filteredSignal = (*filter) * (*receivedSignalPsd); + NS_LOG_DEBUG ("Signal power received (watts) before antenna gain: " << Integral (filteredSignal)); + double rxPowerPerBandW = Integral (filteredSignal) * DbToRatio (GetRxGain ()); + totalRxPowerW += rxPowerPerBandW; + rxPowerW.insert ({filteredBand, rxPowerPerBandW}); + NS_LOG_DEBUG ("Signal power received after antenna gain for " << channelWidth << " MHz channel: " << rxPowerPerBandW << " W (" << WToDbm (rxPowerPerBandW) << " dBm)"); + } + + for (uint16_t bw = 160; bw > 20; bw = bw / 2) //20 MHz is handled apart since the totalRxPowerW is computed through it + { + for (uint8_t i = 0; i < (channelWidth / bw); i++) + { + NS_ASSERT (channelWidth >= bw); + WifiSpectrumBand filteredBand = GetBand (bw, i); + Ptr filter = WifiSpectrumValueHelper::CreateRfFilter (GetFrequency (), channelWidth, GetBandBandwidth (), GetGuardBandwidth (channelWidth), filteredBand); + SpectrumValue filteredSignal = (*filter) * (*receivedSignalPsd); + NS_LOG_DEBUG ("Signal power received (watts) before antenna gain for" << bw << " MHz channel band " << +i << ": " << Integral (filteredSignal)); + double rxPowerPerBandW = Integral (filteredSignal) * DbToRatio (GetRxGain ()); + rxPowerW.insert ({filteredBand, rxPowerPerBandW}); + NS_LOG_DEBUG ("Signal power received after antenna gain for" << bw << " MHz channel band " << +i << ": " << rxPowerPerBandW << " W (" << WToDbm (rxPowerPerBandW) << " dBm)"); + } + } + + + for (uint8_t i = 0; i < (channelWidth / 20); i++) + { + WifiSpectrumBand filteredBand = GetBand (20, i); + Ptr filter = WifiSpectrumValueHelper::CreateRfFilter (GetFrequency (), channelWidth, GetBandBandwidth (), GetGuardBandwidth (channelWidth), filteredBand); + SpectrumValue filteredSignal = (*filter) * (*receivedSignalPsd); + NS_LOG_DEBUG ("Signal power received (watts) before antenna gain for 20 MHz channel band " << +i << ": " << Integral (filteredSignal)); + double rxPowerPerBandW = Integral (filteredSignal) * DbToRatio (GetRxGain ()); + totalRxPowerW += rxPowerPerBandW; + rxPowerW.insert ({filteredBand, rxPowerPerBandW}); + NS_LOG_DEBUG ("Signal power received after antenna gain for 20 MHz channel band " << +i << ": " << rxPowerPerBandW << " W (" << WToDbm (rxPowerPerBandW) << " dBm)"); + } + + NS_LOG_DEBUG ("Total signal power received after antenna gain: " << totalRxPowerW << " W (" << WToDbm (totalRxPowerW) << " dBm)"); Ptr wifiRxParams = DynamicCast (rxParams); // Log the signal arrival to the trace source - m_signalCb (wifiRxParams ? true : false, senderNodeId, WToDbm (rxPowerW), rxDuration); + m_signalCb (wifiRxParams ? true : false, senderNodeId, WToDbm (totalRxPowerW), rxDuration); // Do no further processing if signal is too weak // Current implementation assumes constant RX power over the PPDU duration - if (WToDbm (rxPowerW) < GetRxSensitivity ()) + if (WToDbm (totalRxPowerW) < GetRxSensitivity ()) { - NS_LOG_INFO ("Received signal too weak to process: " << WToDbm (rxPowerW) << " dBm"); + NS_LOG_INFO ("Received signal too weak to process: " << WToDbm (totalRxPowerW) << " dBm"); return; } if (wifiRxParams == 0) @@ -393,4 +457,29 @@ SpectrumWifiPhy::GetGuardBandwidth (uint16_t currentChannelWidth) const return guardBandwidth; } +WifiSpectrumBand +SpectrumWifiPhy::GetBand (uint16_t bandWidth, uint8_t bandIndex) +{ + uint16_t channelWidth = GetChannelWidth (); + uint32_t bandBandwidth = GetBandBandwidth (); + size_t numBandsInChannel = static_cast (channelWidth * 1e6 / bandBandwidth); + size_t numBandsInBand = static_cast (bandWidth * 1e6 / bandBandwidth); + if (numBandsInBand % 2 == 0) + { + numBandsInChannel += 1; // symmetry around center frequency + } + size_t totalNumBands = GetRxSpectrumModel ()->GetNumBands (); + NS_ASSERT_MSG ((numBandsInChannel % 2 == 1) && (totalNumBands % 2 == 1), "Should have odd number of bands"); + NS_ASSERT_MSG ((bandIndex * bandWidth) < channelWidth, "Band index is out of bound"); + WifiSpectrumBand band; + band.first = ((totalNumBands - numBandsInChannel) / 2) + (bandIndex * numBandsInBand); + if (band.first >= totalNumBands / 2) + { + //step past DC + band.first += 1; + } + band.second = band.first + numBandsInBand - 1; + return band; +} + } //namespace ns3 diff --git a/src/wifi/model/spectrum-wifi-phy.h b/src/wifi/model/spectrum-wifi-phy.h index ec6f624af..219cb16d6 100644 --- a/src/wifi/model/spectrum-wifi-phy.h +++ b/src/wifi/model/spectrum-wifi-phy.h @@ -120,7 +120,7 @@ public: * for all SpectrumValues that are passed to StartRx. If 0 is * returned, it means that any model will be accepted. */ - Ptr GetRxSpectrumModel () const; + Ptr GetRxSpectrumModel (); /** * \return the width of each band (Hz) @@ -158,11 +158,22 @@ public: virtual void ConfigureStandardAndBand (WifiPhyStandard standard, WifiPhyBand band); + protected: // Inherited void DoDispose (void); void DoInitialize (void); + /** + * Get the start band index and the stop band index for a given band + * + * \param bandWidth the width of the band to be returned (MHz) + * \param bandIndex the index of the band to be returned + * + * \return a pair of start and stop indexes that defines the band + */ + WifiSpectrumBand GetBand (uint16_t bandWidth, uint8_t bandIndex = 0); + private: /** @@ -181,6 +192,10 @@ private: * Perform run-time spectrum model change */ void ResetSpectrumModel (void); + /** + * This function is called to update the bands handled by the InterferenceHelper. + */ + void UpdateInterferenceHelperBands (void); Ptr m_channel; //!< SpectrumChannel that this SpectrumWifiPhy is connected to diff --git a/src/wifi/model/wifi-phy-header.cc b/src/wifi/model/wifi-phy-header.cc index 6e71c7ddd..55bcd4ae3 100644 --- a/src/wifi/model/wifi-phy-header.cc +++ b/src/wifi/model/wifi-phy-header.cc @@ -195,13 +195,10 @@ LSigHeader::GetSerializedSize (void) const void LSigHeader::SetRate (uint64_t rate, uint16_t channelWidth) { - if (channelWidth == 5) + if (channelWidth < 20) { - rate *= 4; //corresponding 20 MHz rate if 5 MHz is used - } - else if (channelWidth == 10) - { - rate *= 2; //corresponding 20 MHz rate if 10 MHz is used + //conversion for 5 MHz and 10 MHz + rate *= (20 / channelWidth); } /* Here is the binary representation for a given rate: * 6 Mbit/s: 1101 diff --git a/src/wifi/model/wifi-phy.cc b/src/wifi/model/wifi-phy.cc index 9a737e1a4..70adc276c 100644 --- a/src/wifi/model/wifi-phy.cc +++ b/src/wifi/model/wifi-phy.cc @@ -1854,7 +1854,8 @@ WifiPhy::ResumeFromSleep (void) case WifiPhyState::SLEEP: { NS_LOG_DEBUG ("resuming from sleep mode"); - Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW); + uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth (); + Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (primaryChannelWidth)); m_state->SwitchFromSleep (delayUntilCcaEnd); break; } @@ -1885,7 +1886,8 @@ WifiPhy::ResumeFromOff (void) case WifiPhyState::OFF: { NS_LOG_DEBUG ("resuming from off mode"); - Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW); + uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth (); + Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (primaryChannelWidth)); m_state->SwitchFromOff (delayUntilCcaEnd); break; } @@ -2797,11 +2799,21 @@ WifiPhy::StartReceiveHeader (Ptr event) NS_ASSERT (event->GetStartTime () == m_currentEvent->GetStartTime ()); NS_ASSERT (event->GetEndTime () == m_currentEvent->GetEndTime ()); - InterferenceHelper::SnrPer snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (event); + uint16_t channelWidth; + if (event->GetTxVector ().GetChannelWidth () >= 40) + { + channelWidth = 20; //calculate PER on the 20 MHz primary channel for PHY headers + } + else + { + channelWidth = event->GetTxVector ().GetChannelWidth (); + } + auto band = GetBand (channelWidth); + InterferenceHelper::SnrPer snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (event, band); double snr = snrPer.snr; NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per); - if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (event->GetRxPowerW (), snr, m_channelWidth))) + if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (event->GetRxPowerW (band), snr, m_channelWidth))) { NotifyRxBegin (GetAddressedPsduInPpdu (event->GetPpdu ())); @@ -2845,10 +2857,19 @@ WifiPhy::ContinueReceiveHeader (Ptr event) NS_LOG_FUNCTION (this << *event); NS_ASSERT (m_endPhyRxEvent.IsExpired ()); - InterferenceHelper::SnrPer snrPer; - snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (event); + uint16_t channelWidth; + if (event->GetTxVector ().GetChannelWidth () >= 40) + { + channelWidth = 20; //calculate PER on the 20 MHz primary channel for PHY headers + } + else + { + channelWidth = event->GetTxVector ().GetChannelWidth (); + } + InterferenceHelper::SnrPer snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (event, GetBand (channelWidth)); - if (m_random->GetValue () > snrPer.per) //non-HT PHY header reception succeeded + NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per); + if (m_random->GetValue () > snrPer.per) //legacy PHY header reception succeeded { NS_LOG_DEBUG ("Received non-HT PHY header"); WifiTxVector txVector = event->GetTxVector (); @@ -2869,12 +2890,17 @@ WifiPhy::ContinueReceiveHeader (Ptr event) } void -WifiPhy::StartReceivePreamble (Ptr ppdu, double rxPowerW) +WifiPhy::StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxPowersW) { - NS_LOG_FUNCTION (this << *ppdu << rxPowerW); + //The total RX power corresponds to the maximum over all the bands + auto it = std::max_element (rxPowersW.begin (), rxPowersW.end (), + [] (const std::pair& p1, const std::pair& p2) { + return p1.second < p2.second; + }); + NS_LOG_FUNCTION (this << *ppdu << it->second); WifiTxVector txVector = ppdu->GetTxVector (); Time rxDuration = ppdu->GetTxDuration (); - Ptr event = m_interference.Add (ppdu, txVector, rxDuration, rxPowerW); + Ptr event = m_interference.Add (ppdu, txVector, rxDuration, rxPowersW); Time endRx = Simulator::Now () + rxDuration; if (m_state->GetState () == WifiPhyState::OFF) @@ -2936,12 +2962,11 @@ WifiPhy::StartReceivePreamble (Ptr ppdu, double rxPowerW) { AbortCurrentReception (FRAME_CAPTURE_PACKET_SWITCH); NS_LOG_DEBUG ("Switch to new packet"); - StartRx (event, rxPowerW); + StartRx (event); } else { - NS_LOG_DEBUG ("Drop packet because already in Rx (power=" << - rxPowerW << "W)"); + NS_LOG_DEBUG ("Drop packet because already in Rx"); NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), RXING); if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ())) { @@ -2951,8 +2976,7 @@ WifiPhy::StartReceivePreamble (Ptr ppdu, double rxPowerW) } break; case WifiPhyState::TX: - NS_LOG_DEBUG ("Drop packet because already in Tx (power=" << - rxPowerW << "W)"); + NS_LOG_DEBUG ("Drop packet because already in Tx"); NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), TXING); if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ())) { @@ -2969,12 +2993,11 @@ WifiPhy::StartReceivePreamble (Ptr ppdu, double rxPowerW) { AbortCurrentReception (FRAME_CAPTURE_PACKET_SWITCH); NS_LOG_DEBUG ("Switch to new packet"); - StartRx (event, rxPowerW); + StartRx (event); } else { - NS_LOG_DEBUG ("Drop packet because already in Rx (power=" << - rxPowerW << "W)"); + NS_LOG_DEBUG ("Drop packet because already in Rx"); NotifyRxDrop (ppdu->GetPsdu (), RXING); if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ())) { @@ -2985,11 +3008,11 @@ WifiPhy::StartReceivePreamble (Ptr ppdu, double rxPowerW) } else { - StartRx (event, rxPowerW); + StartRx (event); } break; case WifiPhyState::IDLE: - StartRx (event, rxPowerW); + StartRx (event); break; case WifiPhyState::SLEEP: NS_LOG_DEBUG ("Drop packet because in sleep mode"); @@ -3013,8 +3036,8 @@ WifiPhy::MaybeCcaBusyDuration () //not going to be able to synchronize on it //In this model, CCA becomes busy when the aggregation of all signals as //tracked by the InterferenceHelper class is higher than the CcaBusyThreshold - - Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW); + uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth (); + Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (primaryChannelWidth)); if (!delayUntilCcaEnd.IsZero ()) { m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd); @@ -3030,10 +3053,12 @@ WifiPhy::StartReceivePayload (Ptr event) bool canReceivePayload = false; Ptr ppdu = event->GetPpdu (); WifiModulationClass modulation = ppdu->GetModulation (); + //calculate PER on the primary 20 MHz channel for PHY headers + uint16_t primaryChannelWidth = std::min (event->GetTxVector ().GetChannelWidth (), static_cast (20)); + auto primaryBand = GetBand (primaryChannelWidth); if (modulation >= WIFI_MOD_CLASS_HT) { - InterferenceHelper::SnrPer snrPer; - snrPer = m_interference.CalculateHtPhyHeaderSnrPer (event); + InterferenceHelper::SnrPer snrPer = m_interference.CalculateHtPhyHeaderSnrPer (event, primaryBand); NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per); canReceivePayload = (m_random->GetValue () > snrPer.per); } @@ -3103,7 +3128,7 @@ WifiPhy::StartReceivePayload (Ptr event) if (modulation == WIFI_MOD_CLASS_HE) { HePreambleParameters params; - params.rssiW = event->GetRxPowerW (); + params.rssiW = event->GetRxPowerW (primaryBand); params.bssColor = event->GetTxVector ().GetBssColor (); NotifyEndOfHePreamble (params); } @@ -3177,7 +3202,8 @@ WifiPhy::EndOfMpdu (Ptr event, Ptr psdu, size_t mpduIndex Ptr ppdu = event->GetPpdu (); uint16_t staId = GetStaId (); WifiTxVector txVector = event->GetTxVector (); - double snr = m_interference.CalculateSnr (event, txVector.GetNss (staId)); + uint16_t channelWidth = std::min (GetChannelWidth (), txVector.GetChannelWidth ()); + double snr = m_interference.CalculateSnr (event, channelWidth, txVector.GetNss (staId), GetBand (channelWidth)); std::pair rxInfo = GetReceptionStatus (psdu, event, staId, relativeStart, mpduDuration); NS_LOG_DEBUG ("Extracted MPDU #" << mpduIndex << ": duration: " << mpduDuration.GetNanoSeconds () << "ns" << @@ -3212,7 +3238,8 @@ WifiPhy::EndReceive (Ptr event) NotifyRxEnd (psdu); WifiTxVector txVector = event->GetTxVector (); - double snr = m_interference.CalculateSnr (event, txVector.GetNss (staId)); + uint16_t channelWidth = std::min (GetChannelWidth (), txVector.GetChannelWidth ()); + double snr = m_interference.CalculateSnr (event, channelWidth, txVector.GetNss (staId), GetBand (channelWidth)); if (std::count (m_statusPerMpdu.begin (), m_statusPerMpdu.end (), true)) { //At least one MPDU has been successfully received @@ -3235,8 +3262,8 @@ WifiPhy::GetReceptionStatus (Ptr psdu, Ptr event, uint16_ Time relativeMpduStart, Time mpduDuration) { NS_LOG_FUNCTION (this << *psdu << *event << staId << relativeMpduStart << mpduDuration); - InterferenceHelper::SnrPer snrPer; - snrPer = m_interference.CalculatePayloadSnrPer (event, staId, std::make_pair (relativeMpduStart, relativeMpduStart + mpduDuration)); + uint16_t channelWidth = std::min (GetChannelWidth (), event->GetTxVector ().GetChannelWidth ()); + InterferenceHelper::SnrPer snrPer = m_interference.CalculatePayloadSnrPer (event, channelWidth, GetBand (channelWidth), staId, std::make_pair (relativeMpduStart, relativeMpduStart + mpduDuration)); WifiMode mode = event->GetTxVector ().GetMode (staId); NS_LOG_DEBUG ("mode=" << (mode.GetDataRate (event->GetTxVector (), staId)) << @@ -3248,8 +3275,8 @@ WifiPhy::GetReceptionStatus (Ptr psdu, Ptr event, uint16_ // Receive error model is optional, if we have an error model and // it indicates that the packet is corrupt, drop the packet. SignalNoiseDbm signalNoise; - signalNoise.signal = WToDbm (event->GetRxPowerW ()); - signalNoise.noise = WToDbm (event->GetRxPowerW () / snrPer.snr); + signalNoise.signal = WToDbm (event->GetRxPowerW (GetBand (channelWidth))); + signalNoise.noise = WToDbm (event->GetRxPowerW (GetBand (channelWidth)) / snrPer.snr); if (m_random->GetValue () > snrPer.per && !(m_postReceptionErrorModel && m_postReceptionErrorModel->IsCorrupt (psdu->GetPacket ()->Copy ()))) { @@ -4525,7 +4552,8 @@ WifiPhy::SwitchMaybeToCcaBusy (void) //In this model, CCA becomes busy when the aggregation of all signals as //tracked by the InterferenceHelper class is higher than the CcaBusyThreshold - Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW); + uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth (); + Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaEdThresholdW, GetBand (primaryChannelWidth)); if (!delayUntilCcaEnd.IsZero ()) { NS_LOG_DEBUG ("Calling SwitchMaybeToCcaBusy for " << delayUntilCcaEnd.As (Time::S)); @@ -4592,8 +4620,11 @@ WifiPhy::GetTxPowerForTransmission (WifiTxVector txVector) const } void -WifiPhy::StartRx (Ptr event, double rxPowerW) +WifiPhy::StartRx (Ptr event) { + uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth (); + auto primaryBand = GetBand (primaryChannelWidth); + double rxPowerW = event->GetRxPowerW (primaryBand); NS_LOG_FUNCTION (this << *event << rxPowerW); NS_LOG_DEBUG ("sync to signal (power=" << rxPowerW << "W)"); @@ -4605,7 +4636,7 @@ WifiPhy::StartRx (Ptr event, double rxPowerW) Time remainingRxDuration = event->GetDuration () - startOfPreambleDuration; m_endPreambleDetectionEvent = Simulator::Schedule (startOfPreambleDuration, &WifiPhy::StartReceiveHeader, this, event); } - else if ((m_frameCaptureModel != 0) && (rxPowerW > m_currentEvent->GetRxPowerW ())) + else if ((m_frameCaptureModel != 0) && (rxPowerW > m_currentEvent->GetRxPowerW (primaryBand))) { NS_LOG_DEBUG ("Received a stronger signal during preamble detection: drop current packet and switch to new packet"); NotifyRxDrop (GetAddressedPsduInPpdu (m_currentEvent->GetPpdu ()), PREAMBLE_DETECTION_PACKET_SWITCH); @@ -4668,6 +4699,15 @@ WifiPhy::GetStaId (void) const return SU_STA_ID; } +WifiSpectrumBand +WifiPhy::GetBand (uint16_t /*bandWidth*/, uint8_t /*bandIndex*/) +{ + WifiSpectrumBand band; + band.first = 0; + band.second = 0; + return band; +} + int64_t WifiPhy::AssignStreams (int64_t stream) { diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index 9dfb09ffe..4c9b3e289 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -153,6 +153,19 @@ public: WifiPhy (); virtual ~WifiPhy (); + /** + * A pair of a channel number and a WifiPhyBand + */ + typedef std::pair ChannelNumberBandPair; + /** + * A pair of a ChannelNumberBandPair and a WifiPhyStandard + */ + typedef std::pair ChannelNumberStandardPair; + /** + * A pair of a center frequency (MHz) and a channel width (MHz) + */ + typedef std::pair FrequencyWidthPair; + /** * Return the WifiPhyStateHelper of this PHY * @@ -195,9 +208,9 @@ public: * Start receiving the PHY preamble of a PPDU (i.e. the first bit of the preamble has arrived). * * \param ppdu the arriving PPDU - * \param rxPowerW the receive power in W + * \param rxPowersW the receive power in W per 20 MHz channel band */ - void StartReceivePreamble (Ptr ppdu, double rxPowerW); + void StartReceivePreamble (Ptr ppdu, RxPowerWattPerChannelBand rxPowersW); /** * Start receiving the PHY header of a PPDU (i.e. after the end of receiving the preamble). @@ -223,7 +236,7 @@ public: /** * The last symbol of the PPDU has arrived. * - * \param event the corresponding event of the first time the packet arrives (also storing packet and TxVector information) + * \param event the event holding incoming PPDU's information */ void EndReceive (Ptr event); @@ -730,19 +743,6 @@ public: */ bool DefineChannelNumber (uint8_t channelNumber, WifiPhyBand band, WifiPhyStandard standard, uint16_t frequency, uint16_t channelWidth); - /** - * A pair of a channel number and a WifiPhyBand - */ - typedef std::pair ChannelNumberBandPair; - /** - * A pair of a ChannelNumberBandPair and a WifiPhyStandard - */ - typedef std::pair ChannelNumberStandardPair; - /** - * A pair of a center frequency (MHz) and a channel width (MHz) - */ - typedef std::pair FrequencyWidthPair; - /** * Return the Channel this WifiPhy is connected to. * @@ -1771,6 +1771,16 @@ protected: */ virtual uint16_t GetStaId (void) const; + /** + * Get the start band index and the stop band index for a given band + * + * \param bandWidth the width of the band to be returned (MHz) + * \param bandIndex the index of the band to be returned + * + * \return a pair of start and stop indexes that defines the band + */ + virtual WifiSpectrumBand GetBand (uint16_t bandWidth, uint8_t bandIndex = 0); + InterferenceHelper m_interference; //!< Pointer to InterferenceHelper Ptr m_random; //!< Provides uniform random variables. Ptr m_state; //!< Pointer to WifiPhyStateHelper @@ -1897,9 +1907,8 @@ private: * Starting receiving the PPDU after having detected the medium is idle or after a reception switch. * * \param event the event holding incoming PPDU's information - * \param rxPowerW the receive power in W */ - void StartRx (Ptr event, double rxPowerW); + void StartRx (Ptr event); /** * Get the reception status for the provided MPDU and notify. * diff --git a/src/wifi/model/wifi-tx-vector.cc b/src/wifi/model/wifi-tx-vector.cc index 061a85897..a259a7ad4 100644 --- a/src/wifi/model/wifi-tx-vector.cc +++ b/src/wifi/model/wifi-tx-vector.cc @@ -377,6 +377,11 @@ WifiTxVector::GetHeMuUserInfoMap (void) const std::ostream & operator << ( std::ostream &os, const WifiTxVector &v) { + if (!v.IsValid ()) + { + os << "TXVECTOR not valid"; + return os; + } os << "txpwrlvl: " << +v.GetTxPowerLevel () << " preamble: " << v.GetPreambleType () << " channel width: " << v.GetChannelWidth () diff --git a/src/wifi/model/yans-wifi-channel.cc b/src/wifi/model/yans-wifi-channel.cc index f176822dc..20dc42bde 100644 --- a/src/wifi/model/yans-wifi-channel.cc +++ b/src/wifi/model/yans-wifi-channel.cc @@ -133,7 +133,9 @@ YansWifiChannel::Receive (Ptr phy, Ptr ppdu, double rxPow NS_LOG_INFO ("Received signal too weak to process: " << rxPowerDbm << " dBm"); return; } - phy->StartReceivePreamble (ppdu, DbmToW (rxPowerDbm + phy->GetRxGain ())); + RxPowerWattPerChannelBand rxPowerW; + rxPowerW.insert ({std::make_pair (0, 0), (DbmToW (rxPowerDbm + phy->GetRxGain ()))}); //dummy band for YANS + phy->StartReceivePreamble (ppdu, rxPowerW); } std::size_t diff --git a/src/wifi/model/yans-wifi-phy.cc b/src/wifi/model/yans-wifi-phy.cc index 2ea53d3a1..5f32e79dd 100644 --- a/src/wifi/model/yans-wifi-phy.cc +++ b/src/wifi/model/yans-wifi-phy.cc @@ -45,6 +45,11 @@ YansWifiPhy::GetTypeId (void) YansWifiPhy::YansWifiPhy () { NS_LOG_FUNCTION (this); + //add dummy band for Yans + WifiSpectrumBand band; + band.first = 0; + band.second = 0; + m_interference.AddBand (band); } YansWifiPhy::~YansWifiPhy () diff --git a/src/wifi/test/inter-bss-test-suite.cc b/src/wifi/test/inter-bss-test-suite.cc index c12ea0009..4d081179b 100644 --- a/src/wifi/test/inter-bss-test-suite.cc +++ b/src/wifi/test/inter-bss-test-suite.cc @@ -515,7 +515,7 @@ TestInterBssConstantObssPdAlgo::DoRun (void) m_bssColor3 = 3; RunOne (); - //Test case 3: CCA CS Threshold = < m_obssPdLevelDbm = m_obssRxPowerDbm + //Test case 3: CCA CS Threshold < m_obssPdLevelDbm = m_obssRxPowerDbm m_obssPdLevelDbm = -72; m_obssRxPowerDbm = -72; m_bssColor1 = 1; diff --git a/src/wifi/test/wifi-transmit-mask-test.cc b/src/wifi/test/wifi-transmit-mask-test.cc index a38432bf1..8fb2d2c9d 100644 --- a/src/wifi/test/wifi-transmit-mask-test.cc +++ b/src/wifi/test/wifi-transmit-mask-test.cc @@ -245,7 +245,7 @@ WifiTransmitMaskTestSuite::WifiTransmitMaskTestSuite () : TestSuite ("wifi-transmit-mask", UNIT) { // LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL); -// LogComponentEnable ("WifiTransmitMaskTestSuite", logLevel); +// LogComponentEnable ("WifiTransmitMaskTest", logLevel); // LogComponentEnable ("WifiSpectrumValueHelper", logLevel); NS_LOG_INFO ("Creating WifiTransmitMaskTestSuite");