1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2005,2006 INRIA
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 * Sébastien Deronne <sebastien.deronne@gmail.com>
20 */
21
22 #include <numeric>
23 #include <algorithm>
24 #include "ns3/simulator.h"
25 #include "ns3/log.h"
26 #include "ns3/packet.h"
27 #include "interference-helper.h"
28 #include "wifi-phy.h"
29 #include "error-rate-model.h"
30 #include "wifi-utils.h"
31 #include "wifi-psdu.h"
32
33 namespace ns3 {
34
35 NS_LOG_COMPONENT_DEFINE ("InterferenceHelper");
36
37 /****************************************************************
38 * PHY event class
39 ****************************************************************/
40
Event(Ptr<const WifiPpdu> ppdu,const WifiTxVector & txVector,Time duration,RxPowerWattPerChannelBand && rxPower)41 Event::Event (Ptr<const WifiPpdu> ppdu, const WifiTxVector& txVector, Time duration, RxPowerWattPerChannelBand&& rxPower)
42 : m_ppdu (ppdu),
43 m_txVector (txVector),
44 m_startTime (Simulator::Now ()),
45 m_endTime (m_startTime + duration),
46 m_rxPowerW (std::move (rxPower))
47 {
48 }
49
~Event()50 Event::~Event ()
51 {
52 m_ppdu = 0;
53 m_rxPowerW.clear ();
54 }
55
56 Ptr<const WifiPpdu>
GetPpdu(void) const57 Event::GetPpdu (void) const
58 {
59 return m_ppdu;
60 }
61
62 Time
GetStartTime(void) const63 Event::GetStartTime (void) const
64 {
65 return m_startTime;
66 }
67
68 Time
GetEndTime(void) const69 Event::GetEndTime (void) const
70 {
71 return m_endTime;
72 }
73
74 Time
GetDuration(void) const75 Event::GetDuration (void) const
76 {
77 return m_endTime - m_startTime;
78 }
79
80 double
GetRxPowerW(void) const81 Event::GetRxPowerW (void) const
82 {
83 NS_ASSERT (m_rxPowerW.size () > 0);
84 //The total RX power corresponds to the maximum over all the bands
85 auto it = std::max_element (m_rxPowerW.begin (), m_rxPowerW.end (),
86 [] (const std::pair<WifiSpectrumBand, double>& p1, const std::pair<WifiSpectrumBand, double>& p2) {
87 return p1.second < p2.second;
88 });
89 return it->second;
90 }
91
92 double
GetRxPowerW(WifiSpectrumBand band) const93 Event::GetRxPowerW (WifiSpectrumBand band) const
94 {
95 auto it = m_rxPowerW.find (band);
96 NS_ASSERT (it != m_rxPowerW.end ());
97 return it->second;
98 }
99
100 const RxPowerWattPerChannelBand&
GetRxPowerWPerBand(void) const101 Event::GetRxPowerWPerBand (void) const
102 {
103 return m_rxPowerW;
104 }
105
106 const WifiTxVector&
GetTxVector(void) const107 Event::GetTxVector (void) const
108 {
109 return m_txVector;
110 }
111
112 void
UpdateRxPowerW(const RxPowerWattPerChannelBand & rxPower)113 Event::UpdateRxPowerW (const RxPowerWattPerChannelBand& rxPower)
114 {
115 NS_ASSERT (rxPower.size () == m_rxPowerW.size ());
116 //Update power band per band
117 for (auto & currentRxPowerW : m_rxPowerW)
118 {
119 auto band = currentRxPowerW.first;
120 auto it = rxPower.find (band);
121 if (it != rxPower.end ())
122 {
123 currentRxPowerW.second += it->second;
124 }
125 }
126 }
127
operator <<(std::ostream & os,const Event & event)128 std::ostream & operator << (std::ostream &os, const Event &event)
129 {
130 os << "start=" << event.GetStartTime () << ", end=" << event.GetEndTime ()
131 << ", TXVECTOR=" << event.GetTxVector ()
132 << ", power=" << event.GetRxPowerW () << "W"
133 << ", PPDU=" << event.GetPpdu ();
134 return os;
135 }
136
137 /****************************************************************
138 * Class which records SNIR change events for a
139 * short period of time.
140 ****************************************************************/
141
NiChange(double power,Ptr<Event> event)142 InterferenceHelper::NiChange::NiChange (double power, Ptr<Event> event)
143 : m_power (power),
144 m_event (event)
145 {
146 }
147
~NiChange()148 InterferenceHelper::NiChange::~NiChange ()
149 {
150 m_event = 0;
151 }
152
153 double
GetPower(void) const154 InterferenceHelper::NiChange::GetPower (void) const
155 {
156 return m_power;
157 }
158
159 void
AddPower(double power)160 InterferenceHelper::NiChange::AddPower (double power)
161 {
162 m_power += power;
163 }
164
165 Ptr<Event>
GetEvent(void) const166 InterferenceHelper::NiChange::GetEvent (void) const
167 {
168 return m_event;
169 }
170
171
172 /****************************************************************
173 * The actual InterferenceHelper
174 ****************************************************************/
175
InterferenceHelper()176 InterferenceHelper::InterferenceHelper ()
177 : m_errorRateModel (0),
178 m_numRxAntennas (1),
179 m_rxing (false)
180 {
181 }
182
~InterferenceHelper()183 InterferenceHelper::~InterferenceHelper ()
184 {
185 RemoveBands ();
186 m_errorRateModel = 0;
187 }
188
189 Ptr<Event>
Add(Ptr<const WifiPpdu> ppdu,const WifiTxVector & txVector,Time duration,RxPowerWattPerChannelBand & rxPowerW,bool isStartOfdmaRxing)190 InterferenceHelper::Add (Ptr<const WifiPpdu> ppdu, const WifiTxVector& txVector, Time duration, RxPowerWattPerChannelBand& rxPowerW, bool isStartOfdmaRxing)
191 {
192 Ptr<Event> event = Create<Event> (ppdu, txVector, duration, std::move (rxPowerW));
193 AppendEvent (event, isStartOfdmaRxing);
194 return event;
195 }
196
197 void
AddForeignSignal(Time duration,RxPowerWattPerChannelBand & rxPowerW)198 InterferenceHelper::AddForeignSignal (Time duration, RxPowerWattPerChannelBand& rxPowerW)
199 {
200 // Parameters other than duration and rxPowerW are unused for this type
201 // of signal, so we provide dummy versions
202 WifiMacHeader hdr;
203 hdr.SetType (WIFI_MAC_QOSDATA);
204 hdr.SetQosTid (0);
205 Ptr<WifiPpdu> fakePpdu = Create<WifiPpdu> (Create<WifiPsdu> (Create<Packet> (0), hdr),
206 WifiTxVector ());
207 Add (fakePpdu, WifiTxVector (), duration, rxPowerW);
208 }
209
210 void
RemoveBands(void)211 InterferenceHelper::RemoveBands(void)
212 {
213 NS_LOG_FUNCTION (this);
214 for (auto it : m_niChangesPerBand)
215 {
216 it.second.clear ();
217 }
218 m_niChangesPerBand.clear();
219 m_firstPowerPerBand.clear();
220 }
221
222 void
AddBand(WifiSpectrumBand band)223 InterferenceHelper::AddBand (WifiSpectrumBand band)
224 {
225 NS_LOG_FUNCTION (this << band.first << band.second);
226 NS_ASSERT (m_niChangesPerBand.find (band) == m_niChangesPerBand.end ());
227 NiChanges niChanges;
228 auto result = m_niChangesPerBand.insert ({band, niChanges});
229 NS_ASSERT (result.second);
230 // Always have a zero power noise event in the list
231 AddNiChangeEvent (Time (0), NiChange (0.0, 0), result.first);
232 m_firstPowerPerBand.insert ({band, 0.0});
233 }
234
235 void
SetNoiseFigure(double value)236 InterferenceHelper::SetNoiseFigure (double value)
237 {
238 m_noiseFigure = value;
239 }
240
241 void
SetErrorRateModel(const Ptr<ErrorRateModel> rate)242 InterferenceHelper::SetErrorRateModel (const Ptr<ErrorRateModel> rate)
243 {
244 m_errorRateModel = rate;
245 }
246
247 Ptr<ErrorRateModel>
GetErrorRateModel(void) const248 InterferenceHelper::GetErrorRateModel (void) const
249 {
250 return m_errorRateModel;
251 }
252
253 void
SetNumberOfReceiveAntennas(uint8_t rx)254 InterferenceHelper::SetNumberOfReceiveAntennas (uint8_t rx)
255 {
256 m_numRxAntennas = rx;
257 }
258
259 Time
GetEnergyDuration(double energyW,WifiSpectrumBand band)260 InterferenceHelper::GetEnergyDuration (double energyW, WifiSpectrumBand band)
261 {
262 Time now = Simulator::Now ();
263 auto niIt = m_niChangesPerBand.find (band);
264 NS_ASSERT (niIt != m_niChangesPerBand.end ());
265 auto i = GetPreviousPosition (now, niIt);
266 Time end = i->first;
267 for (; i != niIt->second.end (); ++i)
268 {
269 double noiseInterferenceW = i->second.GetPower ();
270 end = i->first;
271 if (noiseInterferenceW < energyW)
272 {
273 break;
274 }
275 }
276 return end > now ? end - now : MicroSeconds (0);
277 }
278
279 void
AppendEvent(Ptr<Event> event,bool isStartOfdmaRxing)280 InterferenceHelper::AppendEvent (Ptr<Event> event, bool isStartOfdmaRxing)
281 {
282 NS_LOG_FUNCTION (this << event << isStartOfdmaRxing);
283 for (auto const& it : event->GetRxPowerWPerBand ())
284 {
285 WifiSpectrumBand band = it.first;
286 auto niIt = m_niChangesPerBand.find (band);
287 NS_ASSERT (niIt != m_niChangesPerBand.end ());
288 double previousPowerStart = 0;
289 double previousPowerEnd = 0;
290 auto previousPowerPosition = GetPreviousPosition (event->GetStartTime (), niIt);
291 previousPowerStart = previousPowerPosition->second.GetPower ();
292 previousPowerEnd = GetPreviousPosition (event->GetEndTime (), niIt)->second.GetPower ();
293 if (!m_rxing)
294 {
295 m_firstPowerPerBand.find (band)->second = previousPowerStart;
296 // Always leave the first zero power noise event in the list
297 niIt->second.erase (++(niIt->second.begin ()), ++previousPowerPosition);
298 }
299 else if (isStartOfdmaRxing)
300 {
301 //When the first UL-OFDMA payload is received, we need to set m_firstPowerPerBand
302 //so that it takes into account interferences that arrived between the start of the
303 //UL MU transmission and the start of UL-OFDMA payload.
304 m_firstPowerPerBand.find (band)->second = previousPowerStart;
305 }
306 auto first = AddNiChangeEvent (event->GetStartTime (), NiChange (previousPowerStart, event), niIt);
307 auto last = AddNiChangeEvent (event->GetEndTime (), NiChange (previousPowerEnd, event), niIt);
308 for (auto i = first; i != last; ++i)
309 {
310 i->second.AddPower (it.second);
311 }
312 }
313 }
314
315 void
UpdateEvent(Ptr<Event> event,const RxPowerWattPerChannelBand & rxPower)316 InterferenceHelper::UpdateEvent (Ptr<Event> event, const RxPowerWattPerChannelBand& rxPower)
317 {
318 NS_LOG_FUNCTION (this << event);
319 //This is called for UL MU events, in order to scale power as long as UL MU PPDUs arrive
320 for (auto const& it : rxPower)
321 {
322 WifiSpectrumBand band = it.first;
323 auto niIt = m_niChangesPerBand.find (band);
324 NS_ASSERT (niIt != m_niChangesPerBand.end ());
325 auto first = GetPreviousPosition (event->GetStartTime (), niIt);
326 auto last = GetPreviousPosition (event->GetEndTime (), niIt);
327 for (auto i = first; i != last; ++i)
328 {
329 i->second.AddPower (it.second);
330 }
331 }
332 event->UpdateRxPowerW (rxPower);
333 }
334
335 double
CalculateSnr(double signal,double noiseInterference,uint16_t channelWidth,uint8_t nss) const336 InterferenceHelper::CalculateSnr (double signal, double noiseInterference, uint16_t channelWidth, uint8_t nss) const
337 {
338 NS_LOG_FUNCTION (this << signal << noiseInterference << channelWidth << +nss);
339 //thermal noise at 290K in J/s = W
340 static const double BOLTZMANN = 1.3803e-23;
341 //Nt is the power of thermal noise in W
342 double Nt = BOLTZMANN * 290 * channelWidth * 1e6;
343 //receiver noise Floor (W) which accounts for thermal noise and non-idealities of the receiver
344 double noiseFloor = m_noiseFigure * Nt;
345 double noise = noiseFloor + noiseInterference;
346 double snr = signal / noise; //linear scale
347 NS_LOG_DEBUG ("bandwidth(MHz)=" << channelWidth << ", signal(W)= " << signal << ", noise(W)=" << noiseFloor << ", interference(W)=" << noiseInterference << ", snr=" << RatioToDb(snr) << "dB");
348 if (m_errorRateModel->IsAwgn ())
349 {
350 double gain = 1;
351 if (m_numRxAntennas > nss)
352 {
353 gain = static_cast<double> (m_numRxAntennas) / nss; //compute gain offered by diversity for AWGN
354 }
355 NS_LOG_DEBUG ("SNR improvement thanks to diversity: " << 10 * std::log10 (gain) << "dB");
356 snr *= gain;
357 }
358 return snr;
359 }
360
361 double
CalculateNoiseInterferenceW(Ptr<Event> event,NiChangesPerBand * nis,WifiSpectrumBand band) const362 InterferenceHelper::CalculateNoiseInterferenceW (Ptr<Event> event, NiChangesPerBand *nis, WifiSpectrumBand band) const
363 {
364 NS_LOG_FUNCTION (this << band.first << band.second);
365 auto firstPower_it = m_firstPowerPerBand.find (band);
366 NS_ASSERT (firstPower_it != m_firstPowerPerBand.end ());
367 double noiseInterferenceW = firstPower_it->second;
368 auto niIt = m_niChangesPerBand.find (band);
369 NS_ASSERT (niIt != m_niChangesPerBand.end ());
370 auto it = niIt->second.find (event->GetStartTime ());
371 for (; it != niIt->second.end () && it->first < Simulator::Now (); ++it)
372 {
373 noiseInterferenceW = it->second.GetPower () - event->GetRxPowerW (band);
374 }
375 it = niIt->second.find (event->GetStartTime ());
376 NS_ASSERT (it != niIt->second.end ());
377 for (; it != niIt->second.end () && it->second.GetEvent () != event; ++it);
378 NiChanges ni;
379 ni.emplace (event->GetStartTime (), NiChange (0, event));
380 while (++it != niIt->second.end () && it->second.GetEvent () != event)
381 {
382 ni.insert (*it);
383 }
384 ni.emplace (event->GetEndTime (), NiChange (0, event));
385 nis->insert ({band, ni});
386 NS_ASSERT_MSG (noiseInterferenceW >= 0, "CalculateNoiseInterferenceW returns negative value " << noiseInterferenceW);
387 return noiseInterferenceW;
388 }
389
390 double
CalculateChunkSuccessRate(double snir,Time duration,WifiMode mode,const WifiTxVector & txVector,WifiPpduField field) const391 InterferenceHelper::CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode, const WifiTxVector& txVector, WifiPpduField field) const
392 {
393 if (duration.IsZero ())
394 {
395 return 1.0;
396 }
397 uint64_t rate = mode.GetDataRate (txVector.GetChannelWidth ());
398 uint64_t nbits = static_cast<uint64_t> (rate * duration.GetSeconds ());
399 double csr = m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, nbits, m_numRxAntennas, field);
400 return csr;
401 }
402
403 double
CalculatePayloadChunkSuccessRate(double snir,Time duration,const WifiTxVector & txVector,uint16_t staId) const404 InterferenceHelper::CalculatePayloadChunkSuccessRate (double snir, Time duration, const WifiTxVector& txVector, uint16_t staId) const
405 {
406 if (duration.IsZero ())
407 {
408 return 1.0;
409 }
410 WifiMode mode = txVector.GetMode (staId);
411 uint64_t rate = mode.GetDataRate (txVector, staId);
412 uint64_t nbits = static_cast<uint64_t> (rate * duration.GetSeconds ());
413 nbits /= txVector.GetNss (staId); //divide effective number of bits by NSS to achieve same chunk error rate as SISO for AWGN
414 double csr = m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, nbits, m_numRxAntennas, WIFI_PPDU_FIELD_DATA, staId);
415 return csr;
416 }
417
418 double
CalculatePayloadPer(Ptr<const Event> event,uint16_t channelWidth,NiChangesPerBand * nis,WifiSpectrumBand band,uint16_t staId,std::pair<Time,Time> window) const419 InterferenceHelper::CalculatePayloadPer (Ptr<const Event> event, uint16_t channelWidth,
420 NiChangesPerBand *nis, WifiSpectrumBand band,
421 uint16_t staId, std::pair<Time, Time> window) const
422 {
423 NS_LOG_FUNCTION (this << channelWidth << band.first << band.second << staId << window.first << window.second);
424 double psr = 1.0; /* Packet Success Rate */
425 auto niIt = nis->find (band)->second;
426 auto j = niIt.begin ();
427 Time previous = j->first;
428 WifiMode payloadMode = event->GetTxVector ().GetMode (staId);
429 Time phyPayloadStart = j->first;
430 if (event->GetPpdu ()->GetType () != WIFI_PPDU_TYPE_UL_MU) //j->first corresponds to the start of the UL-OFDMA payload
431 {
432 phyPayloadStart = j->first + WifiPhy::CalculatePhyPreambleAndHeaderDuration (event->GetTxVector ());
433 }
434 Time windowStart = phyPayloadStart + window.first;
435 Time windowEnd = phyPayloadStart + window.second;
436 double noiseInterferenceW = m_firstPowerPerBand.find (band)->second;
437 double powerW = event->GetRxPowerW (band);
438 while (++j != niIt.end ())
439 {
440 Time current = j->first;
441 NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
442 NS_ASSERT (current >= previous);
443 double snr = CalculateSnr (powerW, noiseInterferenceW, channelWidth, event->GetTxVector ().GetNss (staId));
444 //Case 1: Both previous and current point to the windowed payload
445 if (previous >= windowStart)
446 {
447 psr *= CalculatePayloadChunkSuccessRate (snr, Min (windowEnd, current) - previous, event->GetTxVector (), staId);
448 NS_LOG_DEBUG ("Both previous and current point to the windowed payload: mode=" << payloadMode << ", psr=" << psr);
449 }
450 //Case 2: previous is before windowed payload and current is in the windowed payload
451 else if (current >= windowStart)
452 {
453 psr *= CalculatePayloadChunkSuccessRate (snr, Min (windowEnd, current) - windowStart, event->GetTxVector (), staId);
454 NS_LOG_DEBUG ("previous is before windowed payload and current is in the windowed payload: mode=" << payloadMode << ", psr=" << psr);
455 }
456 noiseInterferenceW = j->second.GetPower () - powerW;
457 previous = j->first;
458 if (previous > windowEnd)
459 {
460 NS_LOG_DEBUG ("Stop: new previous=" << previous << " after time window end=" << windowEnd);
461 break;
462 }
463 }
464 double per = 1 - psr;
465 return per;
466 }
467
468 double
CalculatePhyHeaderSectionPsr(Ptr<const Event> event,NiChangesPerBand * nis,uint16_t channelWidth,WifiSpectrumBand band,PhyEntity::PhyHeaderSections phyHeaderSections) const469 InterferenceHelper::CalculatePhyHeaderSectionPsr (Ptr<const Event> event, NiChangesPerBand *nis,
470 uint16_t channelWidth, WifiSpectrumBand band,
471 PhyEntity::PhyHeaderSections phyHeaderSections) const
472 {
473 NS_LOG_FUNCTION (this << band.first << band.second);
474 double psr = 1.0; /* Packet Success Rate */
475 auto niIt = nis->find (band)->second;
476 auto j = niIt.begin ();
477
478 NS_ASSERT (!phyHeaderSections.empty ());
479 Time stopLastSection = Seconds (0);
480 for (const auto & section : phyHeaderSections)
481 {
482 stopLastSection = Max (stopLastSection, section.second.first.second);
483 }
484
485 Time previous = j->first;
486 double noiseInterferenceW = m_firstPowerPerBand.find (band)->second;
487 double powerW = event->GetRxPowerW (band);
488 while (++j != niIt.end ())
489 {
490 Time current = j->first;
491 NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
492 NS_ASSERT (current >= previous);
493 double snr = CalculateSnr (powerW, noiseInterferenceW, channelWidth, 1);
494 for (const auto & section : phyHeaderSections)
495 {
496 Time start = section.second.first.first;
497 Time stop = section.second.first.second;
498
499 if (previous <= stop || current >= start)
500 {
501 Time duration = Min (stop, current) - Max (start, previous);
502 if (duration.IsStrictlyPositive ())
503 {
504 psr *= CalculateChunkSuccessRate (snr, duration, section.second.second, event->GetTxVector (), section.first);
505 NS_LOG_DEBUG ("Current NI change in " << section.first << " [" << start << ", " << stop << "] for "
506 << duration.As (Time::NS) << ": mode=" << section.second.second << ", psr=" << psr);
507 }
508 }
509 }
510 noiseInterferenceW = j->second.GetPower () - powerW;
511 previous = j->first;
512 if (previous > stopLastSection)
513 {
514 NS_LOG_DEBUG ("Stop: new previous=" << previous << " after stop of last section=" << stopLastSection);
515 break;
516 }
517 }
518 return psr;
519 }
520
521 double
CalculatePhyHeaderPer(Ptr<const Event> event,NiChangesPerBand * nis,uint16_t channelWidth,WifiSpectrumBand band,WifiPpduField header) const522 InterferenceHelper::CalculatePhyHeaderPer (Ptr<const Event> event, NiChangesPerBand *nis,
523 uint16_t channelWidth, WifiSpectrumBand band,
524 WifiPpduField header) const
525 {
526 NS_LOG_FUNCTION (this << band.first << band.second << header);
527 auto niIt = nis->find (band)->second;
528 auto phyEntity = WifiPhy::GetStaticPhyEntity (event->GetTxVector ().GetModulationClass ());
529
530 PhyEntity::PhyHeaderSections sections;
531 for (const auto & section : phyEntity->GetPhyHeaderSections (event->GetTxVector (), niIt.begin ()->first))
532 {
533 if (section.first == header)
534 {
535 sections[header] = section.second;
536 }
537 }
538
539 double psr = 1.0;
540 if (!sections.empty () > 0)
541 {
542 psr = CalculatePhyHeaderSectionPsr (event, nis, channelWidth, band, sections);
543 }
544 return 1 - psr;
545 }
546
547 struct PhyEntity::SnrPer
CalculatePayloadSnrPer(Ptr<Event> event,uint16_t channelWidth,WifiSpectrumBand band,uint16_t staId,std::pair<Time,Time> relativeMpduStartStop) const548 InterferenceHelper::CalculatePayloadSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band,
549 uint16_t staId, std::pair<Time, Time> relativeMpduStartStop) const
550 {
551 NS_LOG_FUNCTION (this << channelWidth << band.first << band.second << staId << relativeMpduStartStop.first << relativeMpduStartStop.second);
552 NiChangesPerBand ni;
553 double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band);
554 double snr = CalculateSnr (event->GetRxPowerW (band),
555 noiseInterferenceW,
556 channelWidth,
557 event->GetTxVector ().GetNss (staId));
558
559 /* calculate the SNIR at the start of the MPDU (located through windowing) and accumulate
560 * all SNIR changes in the SNIR vector.
561 */
562 double per = CalculatePayloadPer (event, channelWidth, &ni, band, staId, relativeMpduStartStop);
563
564 return PhyEntity::SnrPer (snr, per);
565 }
566
567 double
CalculateSnr(Ptr<Event> event,uint16_t channelWidth,uint8_t nss,WifiSpectrumBand band) const568 InterferenceHelper::CalculateSnr (Ptr<Event> event, uint16_t channelWidth, uint8_t nss, WifiSpectrumBand band) const
569 {
570 NiChangesPerBand ni;
571 double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band);
572 double snr = CalculateSnr (event->GetRxPowerW (band),
573 noiseInterferenceW,
574 channelWidth,
575 nss);
576 return snr;
577 }
578
579 struct PhyEntity::SnrPer
CalculatePhyHeaderSnrPer(Ptr<Event> event,uint16_t channelWidth,WifiSpectrumBand band,WifiPpduField header) const580 InterferenceHelper::CalculatePhyHeaderSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band,
581 WifiPpduField header) const
582 {
583 NS_LOG_FUNCTION (this << band.first << band.second << header);
584 NiChangesPerBand ni;
585 double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band);
586 double snr = CalculateSnr (event->GetRxPowerW (band),
587 noiseInterferenceW,
588 channelWidth,
589 1);
590
591 /* calculate the SNIR at the start of the PHY header and accumulate
592 * all SNIR changes in the SNIR vector.
593 */
594 double per = CalculatePhyHeaderPer (event, &ni, channelWidth, band, header);
595
596 return PhyEntity::SnrPer (snr, per);
597 }
598
599 void
EraseEvents(void)600 InterferenceHelper::EraseEvents (void)
601 {
602 for (auto niIt = m_niChangesPerBand.begin(); niIt != m_niChangesPerBand.end(); ++niIt)
603 {
604 niIt->second.clear ();
605 // Always have a zero power noise event in the list
606 AddNiChangeEvent (Time (0), NiChange (0.0, 0), niIt);
607 m_firstPowerPerBand.at (niIt->first) = 0.0;
608 }
609 m_rxing = false;
610 }
611
612 InterferenceHelper::NiChanges::iterator
GetNextPosition(Time moment,NiChangesPerBand::iterator niIt)613 InterferenceHelper::GetNextPosition (Time moment, NiChangesPerBand::iterator niIt)
614 {
615 return niIt->second.upper_bound (moment);
616 }
617
618 InterferenceHelper::NiChanges::iterator
GetPreviousPosition(Time moment,NiChangesPerBand::iterator niIt)619 InterferenceHelper::GetPreviousPosition (Time moment, NiChangesPerBand::iterator niIt)
620 {
621 auto it = GetNextPosition (moment, niIt);
622 // This is safe since there is always an NiChange at time 0,
623 // before moment.
624 --it;
625 return it;
626 }
627
628 InterferenceHelper::NiChanges::iterator
AddNiChangeEvent(Time moment,NiChange change,NiChangesPerBand::iterator niIt)629 InterferenceHelper::AddNiChangeEvent (Time moment, NiChange change, NiChangesPerBand::iterator niIt)
630 {
631 return niIt->second.insert (GetNextPosition (moment, niIt), std::make_pair (moment, change));
632 }
633
634 void
NotifyRxStart()635 InterferenceHelper::NotifyRxStart ()
636 {
637 NS_LOG_FUNCTION (this);
638 m_rxing = true;
639 }
640
641 void
NotifyRxEnd(Time endTime)642 InterferenceHelper::NotifyRxEnd (Time endTime)
643 {
644 NS_LOG_FUNCTION (this << endTime);
645 m_rxing = false;
646 //Update m_firstPowerPerBand for frame capture
647 for (auto niIt = m_niChangesPerBand.begin(); niIt != m_niChangesPerBand.end(); ++niIt)
648 {
649 NS_ASSERT (niIt->second.size () > 1);
650 auto it = GetPreviousPosition (endTime, niIt);
651 it--;
652 m_firstPowerPerBand.find (niIt->first)->second = it->second.GetPower ();
653 }
654 }
655
656 } //namespace ns3
657