24 #include "ns3/simulator.h" 26 #include "ns3/packet.h" 44 m_txVector (txVector),
46 m_endTime (m_startTime + duration),
85 [] (
const std::pair<WifiSpectrumBand, double>& p1,
const std::pair<WifiSpectrumBand, double>& p2) {
86 return p1.second < p2.second;
113 os <<
"start=" <<
event.GetStartTime () <<
", end=" <<
event.GetEndTime ()
114 <<
", TXVECTOR=" <<
event.GetTxVector ()
115 <<
", power=" <<
event.GetRxPowerW () <<
"W" 116 <<
", PPDU=" <<
event.GetPpdu ();
170 Ptr<Event> event = Create<Event> (ppdu, txVector, duration, rxPowerW);
182 Ptr<WifiPpdu> fakePpdu = Create<WifiPpdu> (Create<WifiPsdu> (Create<Packet> (0), hdr),
239 for (; i != ni_it->second.end (); ++i)
241 double noiseInterferenceW = i->second.GetPower ();
243 if (noiseInterferenceW < energyW)
256 for (
auto const& it : rxPowerWattPerChannelBand)
261 double previousPowerStart = 0;
262 double previousPowerEnd = 0;
269 ni_it->second.erase (++(ni_it->second.begin ()),
GetNextPosition (event->GetStartTime (), band));
273 for (
auto i =
first; i != last; ++i)
275 i->second.AddPower (it.second);
283 NS_LOG_FUNCTION (
this << signal << noiseInterference << channelWidth << +nss);
285 static const double BOLTZMANN = 1.3803e-23;
287 double Nt = BOLTZMANN * 290 * channelWidth * 1e6;
290 double noise = noiseFloor + noiseInterference;
291 double snr = signal / noise;
292 NS_LOG_DEBUG (
"bandwidth(MHz)=" << channelWidth <<
", signal(W)= " << signal <<
", noise(W)=" << noiseFloor <<
", interference(W)=" << noiseInterference <<
", snr=" <<
RatioToDb(snr) <<
"dB");
298 NS_LOG_DEBUG (
"SNR improvement thanks to diversity: " << 10 * std::log10 (gain) <<
"dB");
309 double noiseInterferenceW = firstPower_it->second;
312 auto it = ni_it->second.find (event->GetStartTime ());
313 for (; it != ni_it->second.end () && it->first <
Simulator::Now (); ++it)
315 noiseInterferenceW = it->second.GetPower () -
event->GetRxPowerW (band);
317 it = ni_it->second.find (event->GetStartTime ());
319 for (; it != ni_it->second.end () && it->second.GetEvent () != event; ++it);
321 ni.emplace (event->GetStartTime (),
NiChange (0, event));
322 while (++it != ni_it->second.end () && it->second.GetEvent () != event)
326 ni.emplace (event->GetEndTime (),
NiChange (0, event));
327 nis->insert ({band, ni});
328 NS_ASSERT_MSG (noiseInterferenceW >= 0,
"CalculateNoiseInterferenceW returns negative value " << noiseInterferenceW);
329 return noiseInterferenceW;
340 uint64_t nbits =
static_cast<uint64_t
> (rate * duration.
GetSeconds ());
341 double csr =
m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, nbits);
353 uint64_t rate = mode.
GetDataRate (txVector, staId);
354 uint64_t nbits =
static_cast<uint64_t
> (rate * duration.
GetSeconds ());
355 nbits /= txVector.
GetNss (staId);
356 double csr =
m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, nbits);
363 uint16_t staId, std::pair<Time, Time>
window)
const 368 auto ni_it = nis->find (band)->second;
369 auto j = ni_it.begin ();
370 Time previous = j->first;
377 Time windowStart = phyPayloadStart +
window.first;
378 Time windowEnd = phyPayloadStart +
window.second;
380 double powerW =
event->GetRxPowerW (band);
381 while (++j != ni_it.end ())
383 Time current = j->first;
384 NS_LOG_DEBUG (
"previous= " << previous <<
", current=" << current);
386 double snr =
CalculateSnr (powerW, noiseInterferenceW, channelWidth, txVector.
GetNss (staId));
388 if (previous >= windowStart)
391 NS_LOG_DEBUG (
"Both previous and current point to the windowed payload: mode=" << payloadMode <<
", psr=" << psr);
394 else if (current >= windowStart)
397 NS_LOG_DEBUG (
"previous is before windowed payload and current is in the windowed payload: mode=" << payloadMode <<
", psr=" << psr);
399 noiseInterferenceW = j->second.GetPower () - powerW;
401 if (previous > windowEnd)
403 NS_LOG_DEBUG (
"Stop: new previous=" << previous <<
" after time window end=" << windowEnd);
407 double per = 1 - psr;
418 auto ni_it = nis->find (band)->second;
419 auto j = ni_it.begin ();
420 Time previous = j->first;
428 double powerW =
event->GetRxPowerW (band);
429 while (++j != ni_it.end ())
431 Time current = j->first;
432 NS_LOG_DEBUG (
"previous= " << previous <<
", current=" << current);
434 double snr =
CalculateSnr (powerW, noiseInterferenceW, channelWidth, 1);
436 if (previous >= phyPayloadStart)
439 NS_LOG_DEBUG (
"Case 1 - previous and current after payload start: nothing to do");
442 else if (previous >= phyTrainingSymbolsStart)
446 NS_LOG_DEBUG (
"Case 2 - previous is in training or in SIG-B: nothing to do");
449 else if (previous >= phyLSigHeaderEnd)
453 NS_LOG_DEBUG (
"Case 3cii - previous is in HT-SIG or SIG-A: nothing to do");
456 else if (previous >= phyHeaderStart)
460 if (current >= phyPayloadStart)
463 NS_LOG_DEBUG (
"Case 4a - previous in L-SIG and current after payload start: mode=" << headerMode <<
", psr=" << psr);
466 else if (current >= phyTrainingSymbolsStart)
470 NS_LOG_DEBUG (
"Case 4a - previous in L-SIG and current is in training or in SIG-B: mode=" << headerMode <<
", psr=" << psr);
473 else if (current >= phyLSigHeaderEnd)
477 NS_LOG_DEBUG (
"Case 4ci - previous is in L-SIG and current in HT-SIG or in SIG-A: mode=" << headerMode <<
", psr=" << psr);
483 NS_LOG_DEBUG (
"Case 4d - current with previous in L-SIG: mode=" << headerMode <<
", psr=" << psr);
490 if (current >= phyPayloadStart)
493 NS_LOG_DEBUG (
"Case 5aii - previous is in the preamble and current is after payload start: mode=" << headerMode <<
", psr=" << psr);
496 else if (current >= phyTrainingSymbolsStart)
500 NS_LOG_DEBUG (
"Case 5b - previous is in the preamble and current is in training or in SIG-B: mode=" << headerMode <<
", psr=" << psr);
503 else if (current >= phyLSigHeaderEnd)
507 NS_LOG_DEBUG (
"Case 5b - previous is in the preamble and current in HT-SIG or in SIG-A: mode=" << headerMode <<
", psr=" << psr);
510 else if (current >= phyHeaderStart)
514 NS_LOG_DEBUG (
"Case 5d - previous is in the preamble and current is in L-SIG: mode=" << headerMode <<
", psr=" << psr);
518 noiseInterferenceW = j->second.GetPower () - powerW;
522 double per = 1 - psr;
533 auto ni_it = nis->find (band)->second;
534 auto j = ni_it.begin ();
535 Time previous = j->first;
543 else if (
IsVht (preamble))
548 else if (
IsHe (preamble))
559 double powerW =
event->GetRxPowerW (band);
560 while (++j != ni_it.end ())
562 Time current = j->first;
563 NS_LOG_DEBUG (
"previous= " << previous <<
", current=" << current);
565 double snr =
CalculateSnr (powerW, noiseInterferenceW, channelWidth, 1);
567 if (previous >= phyPayloadStart)
570 NS_LOG_DEBUG (
"Case 1 - previous and current after payload start: nothing to do");
573 else if (previous >= phyTrainingSymbolsStart)
577 if (current >= phyPayloadStart)
580 NS_LOG_DEBUG (
"Case 2a - previous is in training or in SIG-B and current after payload start: mode=" << mcsHeaderMode <<
", psr=" << psr);
586 NS_LOG_DEBUG (
"Case 2b - previous is in training or in SIG-B and current is in training or in SIG-B: mode=" << mcsHeaderMode <<
", psr=" << psr);
590 else if (previous >= phyLSigHeaderEnd)
594 if (current >= phyPayloadStart)
602 NS_LOG_DEBUG (
"Case 3ai - previous is in SIG-A and current after payload start: mcs mode=" << mcsHeaderMode <<
", non-HT mode=" << headerMode <<
", psr=" << psr);
608 NS_LOG_DEBUG (
"Case 3aii - previous is in HT-SIG and current after payload start: mode=" << mcsHeaderMode <<
", psr=" << psr);
612 else if (current >= phyTrainingSymbolsStart)
620 NS_LOG_DEBUG (
"Case 3bi - previous is in SIG-A and current is in training or in SIG-B: mode=" << headerMode <<
", psr=" << psr);
626 NS_LOG_DEBUG (
"Case 3bii - previous is in HT-SIG and current is in HT training: mode=" << mcsHeaderMode <<
", psr=" << psr);
637 NS_LOG_DEBUG (
"Case 3ci - previous with current in SIG-A: mode=" << headerMode <<
", psr=" << psr);
643 NS_LOG_DEBUG (
"Case 3cii - previous with current in HT-SIG: mode=" << mcsHeaderMode <<
", psr=" << psr);
648 else if (previous >= phyHeaderStart)
652 if (current >= phyPayloadStart)
658 NS_LOG_DEBUG (
"Case 4ai - previous in L-SIG and current after payload start: nothing to do");
661 else if (
IsVht (preamble) ||
IsHe (preamble))
665 NS_LOG_DEBUG (
"Case 4aii - previous is in L-SIG and current after payload start: mcs mode=" << mcsHeaderMode <<
", non-HT mode=" << headerMode <<
", psr=" << psr);
671 NS_LOG_DEBUG (
"Case 4aiii - previous in L-SIG and current after payload start: mcs mode=" << mcsHeaderMode <<
", psr=" << psr);
675 else if (current >= phyTrainingSymbolsStart)
683 NS_LOG_DEBUG (
"Case 4bi - previous is in L-SIG and current in training or in SIG-B: mcs mode=" << mcsHeaderMode <<
", non-HT mode=" << headerMode <<
", psr=" << psr);
689 NS_LOG_DEBUG (
"Case 4bii - previous in L-SIG and current in HT training: mcs mode=" << mcsHeaderMode <<
", psr=" << psr);
693 else if (current >= phyLSigHeaderEnd)
700 NS_LOG_DEBUG (
"Case 4ci - previous is in L-SIG and current in SIG-A: mode=" << headerMode <<
", psr=" << psr);
706 NS_LOG_DEBUG (
"Case 4cii - previous in L-SIG and current in HT-SIG: mcs mode=" << mcsHeaderMode <<
", psr=" << psr);
713 NS_LOG_DEBUG (
"Case 4d - current with previous in L-SIG: nothing to do");
720 if (current >= phyPayloadStart)
726 NS_LOG_DEBUG (
"Case 5ai - previous is in the preamble and current is after payload start: nothing to do");
729 else if (
IsVht (preamble) ||
IsHe (preamble))
733 NS_LOG_DEBUG (
"Case 5aii - previous is in the preamble and current is after payload start: mcs mode=" << mcsHeaderMode <<
", non-HT mode=" << headerMode <<
", psr=" << psr);
739 NS_LOG_DEBUG (
"Case 5aiii - previous is in the preamble and current is after payload start: mcs mode=" << mcsHeaderMode <<
", non-HT mode=" << headerMode <<
", psr=" << psr);
743 else if (current >= phyTrainingSymbolsStart)
751 NS_LOG_DEBUG (
"Case 5bi - previous is in the preamble and current in training or in SIG-B: mcs mode=" << mcsHeaderMode <<
", non-HT mode=" << headerMode <<
", psr=" << psr);
757 NS_LOG_DEBUG (
"Case 5bii - previous is in the preamble and current in HT training: mcs mode=" << mcsHeaderMode <<
", psr=" << psr);
761 else if (current >= phyLSigHeaderEnd)
768 NS_LOG_DEBUG (
"Case 5ci - previous is in preamble and current in SIG-A: mode=" << headerMode <<
", psr=" << psr);
774 NS_LOG_DEBUG (
"Case 5cii - previous in preamble and current in HT-SIG: mcs mode=" << mcsHeaderMode <<
", psr=" << psr);
778 else if (current >= phyHeaderStart)
782 NS_LOG_DEBUG (
"Case 5d - previous is in the preamble and current is in L-SIG: nothing to do");
786 noiseInterferenceW = j->second.GetPower () - powerW;
790 double per = 1 - psr;
795 InterferenceHelper::CalculatePayloadSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band,
796 uint16_t staId, std::pair<Time, Time> relativeMpduStartStop) const
798 NS_LOG_FUNCTION (
this << channelWidth << band.first << band.second << staId << relativeMpduStartStop.first << relativeMpduStartStop.second);
804 event->GetTxVector ().GetNss (staId));
834 uint16_t channelWidth;
835 if (event->GetTxVector ().GetChannelWidth () >= 40)
841 channelWidth =
event->GetTxVector ().GetChannelWidth ();
865 uint16_t channelWidth;
866 if (event->GetTxVector ().GetChannelWidth () >= 40)
872 channelWidth =
event->GetTxVector ().GetChannelWidth ();
904 InterferenceHelper::NiChanges::const_iterator
909 return it->second.upper_bound (moment);
912 InterferenceHelper::NiChanges::const_iterator
922 InterferenceHelper::NiChanges::iterator
927 return it->second.insert (
GetNextPosition (moment, band), std::make_pair (moment, change));
double GetRxPowerW(void) const
Return the total received power (W).
double CalculatePayloadPer(Ptr< const Event > event, uint16_t channelWidth, NiChangesPerBand *nis, WifiSpectrumBand band, uint16_t staId, std::pair< Time, Time > window) const
Calculate the error rate of the given PHY payload only in the provided time window (thus enabling per...
void AddPower(double power)
Add a given amount of power.
Simulation virtual time values and global simulation resolution.
NiChanges::const_iterator GetNextPosition(Time moment, WifiSpectrumBand band) const
Returns an iterator to the first NiChange that is later than moment.
Smart pointer class similar to boost::intrusive_ptr.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
Time GetEnergyDuration(double energyW, WifiSpectrumBand band) const
Control the scheduling of simulation events.
void SetNumberOfReceiveAntennas(uint8_t rx)
Set the number of RX antennas in the receiver corresponding to this interference helper.
Ptr< ErrorRateModel > GetErrorRateModel(void) const
Return the error rate model.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
Time GetEndTime(void) const
Return the end time of the signal.
void RemoveBands(void)
Remove the frequency bands.
handles interference calculations
static WifiMode GetHePhyHeaderMode()
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
double CalculatePayloadChunkSuccessRate(double snir, Time duration, WifiTxVector txVector, uint16_t staId) const
Calculate the success rate of the payload chunk given the SINR, duration, and Wi-Fi mode...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
void SetErrorRateModel(const Ptr< ErrorRateModel > rate)
Set the error rate model for this interference helper.
NiChangesPerBand m_niChangesPerBand
NI Changes for each band.
static Time GetPhyPreambleDuration(WifiTxVector txVector)
Time GetStartTime(void) const
Return the start time of the signal.
Ptr< Event > GetEvent(void) const
Return the event causes the corresponding NI change.
Ptr< const WifiPpdu > GetPpdu(void) const
Return the PPDU.
Event(Ptr< const WifiPpdu > ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPower)
Create an Event with the given parameters.
uint8_t GetNss(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the number of spatial streams.
bool IsVht(WifiPreamble preamble)
Return whether the preamble is a VHT format preamble.
bool IsHe(WifiPreamble preamble)
Return whether the preamble is a HE format preamble.
Ptr< ErrorRateModel > m_errorRateModel
error rate model
Ptr< Event > Add(Ptr< const WifiPpdu > ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPower)
Add the PPDU-related signal to interference helper.
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
double snr
SNR in linear scale.
Ptr< const WifiPpdu > m_ppdu
PPDU.
NiChanges::iterator AddNiChangeEvent(Time moment, NiChange change, WifiSpectrumBand band)
Add NiChange to the list at the appropriate position and return the iterator of the new event...
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode...
double CalculateChunkSuccessRate(double snir, Time duration, WifiMode mode, WifiTxVector txVector) const
Calculate the success rate of the chunk given the SINR, duration, and Wi-Fi mode. ...
WifiPreamble GetPreambleType(void) const
static Time GetPhyHtSigHeaderDuration(WifiPreamble preamble)
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
std::map< WifiSpectrumBand, double > m_firstPowerPerBand
first power of each band in watts
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
static WifiMode GetHtPhyHeaderMode()
bool IsZero(void) const
Exactly equivalent to t == 0.
Time GetDuration(void) const
Return the duration of the signal.
std::map< WifiSpectrumBand, NiChanges > NiChangesPerBand
Map of NiChanges per band.
std::pair< uint32_t, uint32_t > WifiSpectrumBand
typedef for a pair of start and stop sub-band indexes
WifiTxVector GetTxVector(void) const
Return the TXVECTOR of the PPDU.
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
static WifiMode GetVhtPhyHeaderMode()
double m_noiseFigure
noise figure (linear)
static Time GetPhySigA1Duration(WifiPreamble preamble)
double CalculateNonHtPhyHeaderPer(Ptr< const Event > event, NiChangesPerBand *nis, WifiSpectrumBand band) const
Calculate the error rate of the non-HT PHY header.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void NotifyRxStart()
Notify that RX has started.
Noise and Interference (thus Ni) event.
void EraseEvents(void)
Erase all events.
static Time GetPhyTrainingSymbolDuration(WifiTxVector txVector)
uint8_t m_numRxAntennas
the number of RX antennas in the corresponding receiver
static Time Now(void)
Return the current simulation virtual time.
double RatioToDb(double ratio)
Convert from ratio to dB.
static WifiMode GetPhyHeaderMode(WifiTxVector txVector)
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
void AddBand(WifiSpectrumBand band)
Add a frequency band.
double CalculateNoiseInterferenceW(Ptr< Event > event, NiChangesPerBand *nis, WifiSpectrumBand band) const
Calculate noise and interference power in W.
NiChanges::const_iterator GetPreviousPosition(Time moment, WifiSpectrumBand band) const
Returns an iterator to the last NiChange that is before than moment.
void NotifyRxEnd()
Notify that RX has ended.
void AddForeignSignal(Time duration, RxPowerWattPerChannelBand rxPower)
Add a non-Wifi signal to interference helper.
double CalculateHtPhyHeaderPer(Ptr< const Event > event, NiChangesPerBand *nis, WifiSpectrumBand band) const
Calculate the error rate of the HT PHY header.
void SetNoiseFigure(double value)
Set the noise figure.
bool IsHt(WifiPreamble preamble)
Return whether the preamble is a HT format preamble.
RxPowerWattPerChannelBand m_rxPowerW
received power in watts per band
NiChange(double power, Ptr< Event > event)
Create a NiChange at the given time and the amount of NI change.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
static Time GetPhySigA2Duration(WifiPreamble preamble)
WifiTxVector m_txVector
TXVECTOR.
void AppendEvent(Ptr< Event > event)
Append the given Event.
double CalculateSnr(Ptr< Event > event, uint16_t channelWidth, uint8_t nss, WifiSpectrumBand band) const
Calculate the SNIR for the event (starting from now until the event end).
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
double GetPower(void) const
Return the power.
uint16_t GetChannelWidth(void) const
static Time GetPhyHeaderDuration(WifiTxVector txVector)
handles interference calculations
RxPowerWattPerChannelBand GetRxPowerWPerBand(void) const
Return the received power (W) for all bands.
static Time GetPhySigBDuration(WifiPreamble preamble)
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
std::map< WifiSpectrumBand, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
std::multimap< Time, NiChange > NiChanges
typedef for a multimap of NiChange
bool m_rxing
flag whether it is in receiving state
Time m_startTime
start time