A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
interference-helper.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005,2006 INRIA
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 * Sébastien Deronne <sebastien.deronne@gmail.com>
19 */
20
21#include "interference-helper.h"
22
23#include "error-rate-model.h"
25#include "wifi-phy.h"
26#include "wifi-psdu.h"
27#include "wifi-utils.h"
28
29#include "ns3/he-ppdu.h"
30#include "ns3/log.h"
31#include "ns3/packet.h"
32#include "ns3/simulator.h"
33
34#include <algorithm>
35#include <numeric>
36
37namespace ns3
38{
39
40NS_LOG_COMPONENT_DEFINE("InterferenceHelper");
41
42NS_OBJECT_ENSURE_REGISTERED(InterferenceHelper);
43
44/****************************************************************
45 * PHY event class
46 ****************************************************************/
47
49 : m_ppdu(ppdu),
50 m_startTime(Simulator::Now()),
51 m_endTime(m_startTime + duration),
52 m_rxPowerW(std::move(rxPower))
53{
54}
55
58{
59 return m_ppdu;
60}
61
62Time
64{
65 return m_startTime;
66}
67
68Time
70{
71 return m_endTime;
72}
73
74Time
76{
77 return m_endTime - m_startTime;
78}
79
80double
82{
83 NS_ASSERT(!m_rxPowerW.empty());
84 // The total RX power corresponds to the maximum over all the bands
85 auto it =
86 std::max_element(m_rxPowerW.cbegin(),
87 m_rxPowerW.cend(),
88 [](const auto& p1, const auto& p2) { return p1.second < p2.second; });
89 return it->second;
90}
91
92double
94{
95 const auto it = m_rxPowerW.find(band);
96 NS_ASSERT(it != m_rxPowerW.cend());
97 return it->second;
98}
99
102{
103 return m_rxPowerW;
104}
105
106void
108{
109 NS_ASSERT(rxPower.size() == m_rxPowerW.size());
110 // Update power band per band
111 for (auto& currentRxPowerW : m_rxPowerW)
112 {
113 auto band = currentRxPowerW.first;
114 auto it = rxPower.find(band);
115 if (it != rxPower.end())
116 {
117 currentRxPowerW.second += it->second;
118 }
119 }
120}
121
122void
124{
125 m_ppdu = ppdu;
126}
127
128std::ostream&
129operator<<(std::ostream& os, const Event& event)
130{
131 os << "start=" << event.GetStartTime() << ", end=" << event.GetEndTime()
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
143 : m_power(power),
144 m_event(event)
145{
146}
147
149{
150 m_event = nullptr;
151}
152
153double
155{
156 return m_power;
157}
158
159void
161{
162 m_power += power;
163}
164
167{
168 return m_event;
169}
170
171/****************************************************************
172 * The actual InterferenceHelper
173 ****************************************************************/
174
176 : m_errorRateModel(nullptr),
178{
179 NS_LOG_FUNCTION(this);
180}
181
183{
184 NS_LOG_FUNCTION(this);
185}
186
187TypeId
189{
190 static TypeId tid = TypeId("ns3::InterferenceHelper")
192 .SetGroupName("Wifi")
193 .AddConstructor<InterferenceHelper>();
194 return tid;
195}
196
197void
199{
200 NS_LOG_FUNCTION(this);
201 for (auto it : m_niChanges)
202 {
203 it.second.clear();
204 }
205 m_niChanges.clear();
206 m_firstPowers.clear();
207 m_errorRateModel = nullptr;
208}
209
212 Time duration,
214 const FrequencyRange& freqRange,
215 bool isStartHePortionRxing)
216{
217 Ptr<Event> event = Create<Event>(ppdu, duration, std::move(rxPowerW));
218 AppendEvent(event, freqRange, isStartHePortionRxing);
219 return event;
220}
221
222void
225 const FrequencyRange& freqRange)
226{
227 // Parameters other than duration and rxPowerW are unused for this type
228 // of signal, so we provide dummy versions
229 WifiMacHeader hdr;
231 hdr.SetQosTid(0);
232 Ptr<WifiPpdu> fakePpdu = Create<WifiPpdu>(Create<WifiPsdu>(Create<Packet>(0), hdr),
233 WifiTxVector(),
235 Add(fakePpdu, duration, rxPowerW, freqRange);
236}
237
238bool
240{
241 return !m_niChanges.empty();
242}
243
244bool
246{
247 return m_niChanges.contains(band);
248}
249
250void
252{
253 NS_LOG_FUNCTION(this << band);
254 NS_ASSERT(!m_niChanges.contains(band));
255 NS_ASSERT(!m_firstPowers.contains(band));
256 NiChanges niChanges;
257 auto result = m_niChanges.insert({band, niChanges});
258 NS_ASSERT(result.second);
259 // Always have a zero power noise event in the list
260 AddNiChangeEvent(Time(0), NiChange(0.0, nullptr), result.first);
261 m_firstPowers.insert({band, 0.0});
262}
263
264void
265InterferenceHelper::UpdateBands(const std::vector<WifiSpectrumBandInfo>& bands,
266 const FrequencyRange& freqRange)
267{
268 NS_LOG_FUNCTION(this << freqRange);
269 for (auto it = m_niChanges.begin(); it != m_niChanges.end();)
270 {
271 if (!IsBandInFrequencyRange(it->first, freqRange))
272 {
273 it++;
274 continue;
275 }
276 const auto frequencies = it->first.frequencies;
277 const auto found =
278 std::find_if(bands.cbegin(), bands.cend(), [frequencies](const auto& item) {
279 return frequencies == item.frequencies;
280 }) != std::end(bands);
281 if (!found)
282 {
283 // band does not belong to the new bands, erase it
284 m_firstPowers.erase(it->first);
285 it->second.clear();
286 it = m_niChanges.erase(it);
287 }
288 else
289 {
290 it++;
291 }
292 }
293 for (const auto& band : bands)
294 {
295 if (!HasBand(band))
296 {
297 // this is a new band, add it
298 AddBand(band);
299 }
300 }
301}
302
303void
305{
306 m_noiseFigure = value;
307}
308
309void
311{
312 m_errorRateModel = rate;
313}
314
317{
318 return m_errorRateModel;
319}
320
321void
323{
324 m_numRxAntennas = rx;
325}
326
327Time
329{
330 NS_LOG_FUNCTION(this << energyW << band);
331 Time now = Simulator::Now();
332 auto niIt = m_niChanges.find(band);
333 NS_ABORT_IF(niIt == m_niChanges.end());
334 auto i = GetPreviousPosition(now, niIt);
335 Time end = i->first;
336 for (; i != niIt->second.end(); ++i)
337 {
338 double noiseInterferenceW = i->second.GetPower();
339 end = i->first;
340 if (noiseInterferenceW < energyW)
341 {
342 break;
343 }
344 }
345 return end > now ? end - now : MicroSeconds(0);
346}
347
348void
350 const FrequencyRange& freqRange,
351 bool isStartHePortionRxing)
352{
353 NS_LOG_FUNCTION(this << event << freqRange << isStartHePortionRxing);
354 for (const auto& [band, power] : event->GetRxPowerWPerBand())
355 {
356 auto niIt = m_niChanges.find(band);
357 NS_ABORT_IF(niIt == m_niChanges.end());
358 double previousPowerStart = 0;
359 double previousPowerEnd = 0;
360 auto previousPowerPosition = GetPreviousPosition(event->GetStartTime(), niIt);
361 previousPowerStart = previousPowerPosition->second.GetPower();
362 previousPowerEnd = GetPreviousPosition(event->GetEndTime(), niIt)->second.GetPower();
363 if (const auto rxing = (m_rxing.contains(freqRange) && m_rxing.at(freqRange)); !rxing)
364 {
365 m_firstPowers.find(band)->second = previousPowerStart;
366 // Always leave the first zero power noise event in the list
367 niIt->second.erase(++(niIt->second.begin()), ++previousPowerPosition);
368 }
369 else if (isStartHePortionRxing)
370 {
371 // When the first HE portion is received, we need to set m_firstPowerPerBand
372 // so that it takes into account interferences that arrived between the start of the
373 // HE TB PPDU transmission and the start of HE TB payload.
374 m_firstPowers.find(band)->second = previousPowerStart;
375 }
376 auto first =
377 AddNiChangeEvent(event->GetStartTime(), NiChange(previousPowerStart, event), niIt);
378 auto last = AddNiChangeEvent(event->GetEndTime(), NiChange(previousPowerEnd, event), niIt);
379 for (auto i = first; i != last; ++i)
380 {
381 i->second.AddPower(power);
382 }
383 }
384}
385
386void
388{
389 NS_LOG_FUNCTION(this << event);
390 // This is called for UL MU events, in order to scale power as long as UL MU PPDUs arrive
391 for (const auto& [band, power] : rxPower)
392 {
393 auto niIt = m_niChanges.find(band);
394 NS_ABORT_IF(niIt == m_niChanges.end());
395 auto first = GetPreviousPosition(event->GetStartTime(), niIt);
396 auto last = GetPreviousPosition(event->GetEndTime(), niIt);
397 for (auto i = first; i != last; ++i)
398 {
399 i->second.AddPower(power);
400 }
401 }
402 event->UpdateRxPowerW(rxPower);
403}
404
405double
407 double noiseInterference,
408 uint16_t channelWidth,
409 uint8_t nss) const
410{
411 NS_LOG_FUNCTION(this << signal << noiseInterference << channelWidth << +nss);
412 // thermal noise at 290K in J/s = W
413 static const double BOLTZMANN = 1.3803e-23;
414 // Nt is the power of thermal noise in W
415 double Nt = BOLTZMANN * 290 * channelWidth * 1e6;
416 // receiver noise Floor (W) which accounts for thermal noise and non-idealities of the receiver
417 double noiseFloor = m_noiseFigure * Nt;
418 double noise = noiseFloor + noiseInterference;
419 double snr = signal / noise; // linear scale
420 NS_LOG_DEBUG("bandwidth=" << channelWidth << "MHz, signal=" << signal << "W, noise="
421 << noiseFloor << "W, interference=" << noiseInterference
422 << "W, snr=" << RatioToDb(snr) << "dB");
423 if (m_errorRateModel->IsAwgn())
424 {
425 double gain = 1;
426 if (m_numRxAntennas > nss)
427 {
428 gain = static_cast<double>(m_numRxAntennas) /
429 nss; // compute gain offered by diversity for AWGN
430 }
431 NS_LOG_DEBUG("SNR improvement thanks to diversity: " << 10 * std::log10(gain) << "dB");
432 snr *= gain;
433 }
434 return snr;
435}
436
437double
439 NiChangesPerBand& nis,
440 const WifiSpectrumBandInfo& band) const
441{
442 NS_LOG_FUNCTION(this << band);
443 auto firstPower_it = m_firstPowers.find(band);
444 NS_ABORT_IF(firstPower_it == m_firstPowers.end());
445 double noiseInterferenceW = firstPower_it->second;
446 auto niIt = m_niChanges.find(band);
447 NS_ABORT_IF(niIt == m_niChanges.end());
448 const auto now = Simulator::Now();
449 auto it = niIt->second.find(event->GetStartTime());
450 double muMimoPowerW = (event->GetPpdu()->GetType() == WIFI_PPDU_TYPE_UL_MU)
451 ? CalculateMuMimoPowerW(event, band)
452 : 0.0;
453 for (; it != niIt->second.end() && it->first < now; ++it)
454 {
455 if (IsSameMuMimoTransmission(event, it->second.GetEvent()) &&
456 (event != it->second.GetEvent()))
457 {
458 // Do not calculate noiseInterferenceW if events belong to the same MU-MIMO transmission
459 // unless this is the same event
460 continue;
461 }
462 noiseInterferenceW = it->second.GetPower() - event->GetRxPowerW(band) - muMimoPowerW;
463 if (std::abs(noiseInterferenceW) < std::numeric_limits<double>::epsilon())
464 {
465 // fix some possible rounding issues with double values
466 noiseInterferenceW = 0.0;
467 }
468 }
469 it = niIt->second.find(event->GetStartTime());
470 NS_ABORT_IF(it == niIt->second.end());
471 for (; it != niIt->second.end() && it->second.GetEvent() != event; ++it)
472 {
473 ;
474 }
475 NiChanges ni;
476 ni.emplace(event->GetStartTime(), NiChange(0, event));
477 while (++it != niIt->second.end() && it->second.GetEvent() != event)
478 {
479 ni.insert(*it);
480 }
481 ni.emplace(event->GetEndTime(), NiChange(0, event));
482 nis.insert({band, ni});
483 NS_ASSERT_MSG(noiseInterferenceW >= 0.0,
484 "CalculateNoiseInterferenceW returns negative value " << noiseInterferenceW);
485 return noiseInterferenceW;
486}
487
488double
490 const WifiSpectrumBandInfo& band) const
491{
492 auto niIt = m_niChanges.find(band);
493 NS_ASSERT(niIt != m_niChanges.end());
494 auto it = niIt->second.begin();
495 ++it;
496 double muMimoPowerW = 0.0;
497 for (; it != niIt->second.end() && it->first < Simulator::Now(); ++it)
498 {
499 if (IsSameMuMimoTransmission(event, it->second.GetEvent()))
500 {
501 auto hePpdu = DynamicCast<HePpdu>(it->second.GetEvent()->GetPpdu()->Copy());
502 NS_ASSERT(hePpdu);
503 HePpdu::TxPsdFlag psdFlag = hePpdu->GetTxPsdFlag();
504 if (psdFlag == HePpdu::PSD_HE_PORTION)
505 {
506 const auto staId =
507 event->GetPpdu()->GetTxVector().GetHeMuUserInfoMap().cbegin()->first;
508 const auto otherStaId = it->second.GetEvent()
509 ->GetPpdu()
510 ->GetTxVector()
511 .GetHeMuUserInfoMap()
512 .cbegin()
513 ->first;
514 if (staId == otherStaId)
515 {
516 break;
517 }
518 muMimoPowerW += it->second.GetEvent()->GetRxPowerW(band);
519 }
520 }
521 }
522 return muMimoPowerW;
523}
524
525double
527 Time duration,
528 WifiMode mode,
529 const WifiTxVector& txVector,
530 WifiPpduField field) const
531{
532 if (duration.IsZero())
533 {
534 return 1.0;
535 }
536 uint64_t rate = mode.GetDataRate(txVector.GetChannelWidth());
537 auto nbits = static_cast<uint64_t>(rate * duration.GetSeconds());
538 double csr =
539 m_errorRateModel->GetChunkSuccessRate(mode, txVector, snir, nbits, m_numRxAntennas, field);
540 return csr;
541}
542
543double
545 Time duration,
546 const WifiTxVector& txVector,
547 uint16_t staId) const
548{
549 if (duration.IsZero())
550 {
551 return 1.0;
552 }
553 WifiMode mode = txVector.GetMode(staId);
554 uint64_t rate = mode.GetDataRate(txVector, staId);
555 auto nbits = static_cast<uint64_t>(rate * duration.GetSeconds());
556 nbits /= txVector.GetNss(staId); // divide effective number of bits by NSS to achieve same chunk
557 // error rate as SISO for AWGN
558 double csr = m_errorRateModel->GetChunkSuccessRate(mode,
559 txVector,
560 snir,
561 nbits,
564 staId);
565 return csr;
566}
567
568double
570 uint16_t channelWidth,
571 NiChangesPerBand* nis,
572 const WifiSpectrumBandInfo& band,
573 uint16_t staId,
574 std::pair<Time, Time> window) const
575{
576 NS_LOG_FUNCTION(this << channelWidth << band << staId << window.first << window.second);
577 double psr = 1.0; /* Packet Success Rate */
578 const auto& niIt = nis->find(band)->second;
579 auto j = niIt.cbegin();
580 Time previous = j->first;
581 double muMimoPowerW = 0.0;
582 WifiMode payloadMode = event->GetPpdu()->GetTxVector().GetMode(staId);
583 Time phyPayloadStart = j->first;
584 if (event->GetPpdu()->GetType() != WIFI_PPDU_TYPE_UL_MU &&
585 event->GetPpdu()->GetType() !=
586 WIFI_PPDU_TYPE_DL_MU) // j->first corresponds to the start of the MU payload
587 {
588 phyPayloadStart = j->first + WifiPhy::CalculatePhyPreambleAndHeaderDuration(
589 event->GetPpdu()->GetTxVector());
590 }
591 else
592 {
593 muMimoPowerW = CalculateMuMimoPowerW(event, band);
594 }
595 Time windowStart = phyPayloadStart + window.first;
596 Time windowEnd = phyPayloadStart + window.second;
597 NS_ABORT_IF(!m_firstPowers.contains(band));
598 double noiseInterferenceW = m_firstPowers.at(band);
599 double powerW = event->GetRxPowerW(band);
600 while (++j != niIt.cend())
601 {
602 Time current = j->first;
603 NS_LOG_DEBUG("previous= " << previous << ", current=" << current);
604 NS_ASSERT(current >= previous);
605 double snr = CalculateSnr(powerW,
606 noiseInterferenceW,
607 channelWidth,
608 event->GetPpdu()->GetTxVector().GetNss(staId));
609 // Case 1: Both previous and current point to the windowed payload
610 if (previous >= windowStart)
611 {
613 Min(windowEnd, current) - previous,
614 event->GetPpdu()->GetTxVector(),
615 staId);
616 NS_LOG_DEBUG("Both previous and current point to the windowed payload: mode="
617 << payloadMode << ", psr=" << psr);
618 }
619 // Case 2: previous is before windowed payload and current is in the windowed payload
620 else if (current >= windowStart)
621 {
623 Min(windowEnd, current) - windowStart,
624 event->GetPpdu()->GetTxVector(),
625 staId);
627 "previous is before windowed payload and current is in the windowed payload: mode="
628 << payloadMode << ", psr=" << psr);
629 }
630 noiseInterferenceW = j->second.GetPower() - powerW;
631 if (IsSameMuMimoTransmission(event, j->second.GetEvent()))
632 {
633 muMimoPowerW += j->second.GetEvent()->GetRxPowerW(band);
635 "PPDU belongs to same MU-MIMO transmission: muMimoPowerW=" << muMimoPowerW);
636 }
637 noiseInterferenceW -= muMimoPowerW;
638 previous = j->first;
639 if (previous > windowEnd)
640 {
641 NS_LOG_DEBUG("Stop: new previous=" << previous
642 << " after time window end=" << windowEnd);
643 break;
644 }
645 }
646 double per = 1 - psr;
647 return per;
648}
649
650double
652 Ptr<const Event> event,
653 NiChangesPerBand* nis,
654 uint16_t channelWidth,
655 const WifiSpectrumBandInfo& band,
656 PhyEntity::PhyHeaderSections phyHeaderSections) const
657{
658 NS_LOG_FUNCTION(this << band);
659 double psr = 1.0; /* Packet Success Rate */
660 auto niIt = nis->find(band)->second;
661 auto j = niIt.begin();
662
663 NS_ASSERT(!phyHeaderSections.empty());
664 Time stopLastSection = Seconds(0);
665 for (const auto& section : phyHeaderSections)
666 {
667 stopLastSection = Max(stopLastSection, section.second.first.second);
668 }
669
670 Time previous = j->first;
671 NS_ABORT_IF(!m_firstPowers.contains(band));
672 double noiseInterferenceW = m_firstPowers.at(band);
673 double powerW = event->GetRxPowerW(band);
674 while (++j != niIt.end())
675 {
676 Time current = j->first;
677 NS_LOG_DEBUG("previous= " << previous << ", current=" << current);
678 NS_ASSERT(current >= previous);
679 double snr = CalculateSnr(powerW, noiseInterferenceW, channelWidth, 1);
680 for (const auto& section : phyHeaderSections)
681 {
682 Time start = section.second.first.first;
683 Time stop = section.second.first.second;
684
685 if (previous <= stop || current >= start)
686 {
687 Time duration = Min(stop, current) - Max(start, previous);
688 if (duration.IsStrictlyPositive())
689 {
690 psr *= CalculateChunkSuccessRate(snr,
691 duration,
692 section.second.second,
693 event->GetPpdu()->GetTxVector(),
694 section.first);
695 NS_LOG_DEBUG("Current NI change in "
696 << section.first << " [" << start << ", " << stop << "] for "
697 << duration.As(Time::NS) << ": mode=" << section.second.second
698 << ", psr=" << psr);
699 }
700 }
701 }
702 noiseInterferenceW = j->second.GetPower() - powerW;
703 previous = j->first;
704 if (previous > stopLastSection)
705 {
706 NS_LOG_DEBUG("Stop: new previous=" << previous << " after stop of last section="
707 << stopLastSection);
708 break;
709 }
710 }
711 return psr;
712}
713
714double
716 NiChangesPerBand* nis,
717 uint16_t channelWidth,
718 const WifiSpectrumBandInfo& band,
719 WifiPpduField header) const
720{
721 NS_LOG_FUNCTION(this << band << header);
722 auto niIt = nis->find(band)->second;
723 auto phyEntity =
724 WifiPhy::GetStaticPhyEntity(event->GetPpdu()->GetTxVector().GetModulationClass());
725
727 for (const auto& section :
728 phyEntity->GetPhyHeaderSections(event->GetPpdu()->GetTxVector(), niIt.begin()->first))
729 {
730 if (section.first == header)
731 {
732 sections[header] = section.second;
733 }
734 }
735
736 double psr = 1.0;
737 if (!sections.empty())
738 {
739 psr = CalculatePhyHeaderSectionPsr(event, nis, channelWidth, band, sections);
740 }
741 return 1 - psr;
742}
743
746 uint16_t channelWidth,
747 const WifiSpectrumBandInfo& band,
748 uint16_t staId,
749 std::pair<Time, Time> relativeMpduStartStop) const
750{
751 NS_LOG_FUNCTION(this << channelWidth << band << staId << relativeMpduStartStop.first
752 << relativeMpduStartStop.second);
754 double noiseInterferenceW = CalculateNoiseInterferenceW(event, ni, band);
755 double snr = CalculateSnr(event->GetRxPowerW(band),
756 noiseInterferenceW,
757 channelWidth,
758 event->GetPpdu()->GetTxVector().GetNss(staId));
759
760 /* calculate the SNIR at the start of the MPDU (located through windowing) and accumulate
761 * all SNIR changes in the SNIR vector.
762 */
763 double per = CalculatePayloadPer(event, channelWidth, &ni, band, staId, relativeMpduStartStop);
764
765 return PhyEntity::SnrPer(snr, per);
766}
767
768double
770 uint16_t channelWidth,
771 uint8_t nss,
772 const WifiSpectrumBandInfo& band) const
773{
775 double noiseInterferenceW = CalculateNoiseInterferenceW(event, ni, band);
776 double snr = CalculateSnr(event->GetRxPowerW(band), noiseInterferenceW, channelWidth, nss);
777 return snr;
778}
779
782 uint16_t channelWidth,
783 const WifiSpectrumBandInfo& band,
784 WifiPpduField header) const
785{
786 NS_LOG_FUNCTION(this << band << header);
788 double noiseInterferenceW = CalculateNoiseInterferenceW(event, ni, band);
789 double snr = CalculateSnr(event->GetRxPowerW(band), noiseInterferenceW, channelWidth, 1);
790
791 /* calculate the SNIR at the start of the PHY header and accumulate
792 * all SNIR changes in the SNIR vector.
793 */
794 double per = CalculatePhyHeaderPer(event, &ni, channelWidth, band, header);
795
796 return PhyEntity::SnrPer(snr, per);
797}
798
799InterferenceHelper::NiChanges::iterator
800InterferenceHelper::GetNextPosition(Time moment, NiChangesPerBand::iterator niIt)
801{
802 return niIt->second.upper_bound(moment);
803}
804
805InterferenceHelper::NiChanges::iterator
806InterferenceHelper::GetPreviousPosition(Time moment, NiChangesPerBand::iterator niIt)
807{
808 auto it = GetNextPosition(moment, niIt);
809 // This is safe since there is always an NiChange at time 0,
810 // before moment.
811 --it;
812 return it;
813}
814
815InterferenceHelper::NiChanges::iterator
816InterferenceHelper::AddNiChangeEvent(Time moment, NiChange change, NiChangesPerBand::iterator niIt)
817{
818 return niIt->second.insert(GetNextPosition(moment, niIt), {moment, change});
819}
820
821void
823{
824 NS_LOG_FUNCTION(this << freqRange);
825 m_rxing[freqRange] = true;
826}
827
828void
830{
831 NS_LOG_FUNCTION(this << endTime << freqRange);
832 m_rxing.at(freqRange) = false;
833 // Update m_firstPowers for frame capture
834 for (auto niIt = m_niChanges.begin(); niIt != m_niChanges.end(); ++niIt)
835 {
836 if (!IsBandInFrequencyRange(niIt->first, freqRange))
837 {
838 continue;
839 }
840 NS_ASSERT(niIt->second.size() > 1);
841 auto it = GetPreviousPosition(endTime, niIt);
842 it--;
843 m_firstPowers.find(niIt->first)->second = it->second.GetPower();
844 }
845}
846
847bool
849 const FrequencyRange& freqRange) const
850{
851 return ((band.frequencies.second > (freqRange.minFrequency * 1e6)) &&
852 (band.frequencies.first < (freqRange.maxFrequency * 1e6)));
853}
854
855bool
857 Ptr<const Event> otherEvent) const
858{
859 if ((currentEvent->GetPpdu()->GetType() == WIFI_PPDU_TYPE_UL_MU) &&
860 (otherEvent->GetPpdu()->GetType() == WIFI_PPDU_TYPE_UL_MU) &&
861 (currentEvent->GetPpdu()->GetUid() == otherEvent->GetPpdu()->GetUid()))
862 {
863 const auto currentTxVector = currentEvent->GetPpdu()->GetTxVector();
864 const auto otherTxVector = otherEvent->GetPpdu()->GetTxVector();
865 NS_ASSERT(currentTxVector.GetHeMuUserInfoMap().size() == 1);
866 NS_ASSERT(otherTxVector.GetHeMuUserInfoMap().size() == 1);
867 const auto currentUserInfo = currentTxVector.GetHeMuUserInfoMap().cbegin();
868 const auto otherUserInfo = otherTxVector.GetHeMuUserInfoMap().cbegin();
869 return (currentUserInfo->second.ru == otherUserInfo->second.ru);
870 }
871 return false;
872}
873
874} // namespace ns3
#define Max(a, b)
#define Min(a, b)
handles interference calculations
Time m_endTime
end time
Time m_startTime
start time
Event(Ptr< const WifiPpdu > ppdu, Time duration, RxPowerWattPerChannelBand &&rxPower)
Create an Event with the given parameters.
Ptr< const WifiPpdu > GetPpdu() const
Return the PPDU.
Ptr< const WifiPpdu > m_ppdu
PPDU.
void UpdateRxPowerW(const RxPowerWattPerChannelBand &rxPower)
Update the received power (W) for all bands, i.e.
Time GetEndTime() const
Return the end time of the signal.
Time GetDuration() const
Return the duration of the signal.
double GetRxPowerW() const
Return the total received power (W).
RxPowerWattPerChannelBand m_rxPowerW
received power in watts per band
const RxPowerWattPerChannelBand & GetRxPowerWPerBand() const
Return the received power (W) for all bands.
Time GetStartTime() const
Return the start time of the signal.
void UpdatePpdu(Ptr< const WifiPpdu > ppdu)
Update the PPDU that initially generated the event.
TxPsdFlag
The transmit power spectral density flag, namely used to correctly build PSDs for pre-HE and HE porti...
Definition: he-ppdu.h:115
@ PSD_HE_PORTION
HE portion of an HE PPDU.
Definition: he-ppdu.h:117
Noise and Interference (thus Ni) event.
void AddPower(double power)
Add a given amount of power.
NiChange(double power, Ptr< Event > event)
Create a NiChange at the given time and the amount of NI change.
double GetPower() const
Return the power.
Ptr< Event > GetEvent() const
Return the event causes the corresponding NI change.
handles interference calculations
void SetNoiseFigure(double value)
Set the noise figure.
Ptr< Event > Add(Ptr< const WifiPpdu > ppdu, Time duration, RxPowerWattPerChannelBand &rxPower, const FrequencyRange &freqRange, bool isStartHePortionRxing=false)
Add the PPDU-related signal to interference helper.
double m_noiseFigure
noise figure (linear)
std::map< FrequencyRange, bool > m_rxing
flag whether it is in receiving state for a given FrequencyRange
Ptr< ErrorRateModel > GetErrorRateModel() const
Return the error rate model.
NiChanges::iterator AddNiChangeEvent(Time moment, NiChange change, NiChangesPerBand::iterator niIt)
Add NiChange to the list at the appropriate position and return the iterator of the new event.
std::map< WifiSpectrumBandInfo, NiChanges > NiChangesPerBand
Map of NiChanges per band.
void NotifyRxStart(const FrequencyRange &freqRange)
Notify that RX has started.
double CalculateMuMimoPowerW(Ptr< const Event > event, const WifiSpectrumBandInfo &band) const
Calculate power of all other events preceding a given event that belong to the same MU-MIMO transmiss...
uint8_t m_numRxAntennas
the number of RX antennas in the corresponding receiver
bool IsBandInFrequencyRange(const WifiSpectrumBandInfo &band, const FrequencyRange &freqRange) const
Check whether a given band belongs to a given frequency range.
void DoDispose() override
Destructor implementation.
std::multimap< Time, NiChange > NiChanges
typedef for a multimap of NiChange
NiChangesPerBand m_niChanges
NI Changes for each band.
void UpdateBands(const std::vector< WifiSpectrumBandInfo > &bands, const FrequencyRange &freqRange)
Update the frequency bands that belongs to a given frequency range when the spectrum model is changed...
void SetErrorRateModel(const Ptr< ErrorRateModel > rate)
Set the error rate model for this interference helper.
bool HasBands() const
Check whether bands are already tracked by this interference helper.
void AddForeignSignal(Time duration, RxPowerWattPerChannelBand &rxPower, const FrequencyRange &freqRange)
Add a non-Wifi signal to interference helper.
double CalculatePayloadChunkSuccessRate(double snir, Time duration, const WifiTxVector &txVector, uint16_t staId=SU_STA_ID) const
Calculate the success rate of the payload chunk given the SINR, duration, and TXVECTOR.
Ptr< ErrorRateModel > m_errorRateModel
error rate model
NiChanges::iterator GetNextPosition(Time moment, NiChangesPerBand::iterator niIt)
Returns an iterator to the first NiChange that is later than moment.
FirstPowerPerBand m_firstPowers
first power of each band in watts
Time GetEnergyDuration(double energyW, const WifiSpectrumBandInfo &band)
bool IsSameMuMimoTransmission(Ptr< const Event > currentEvent, Ptr< const Event > otherEvent) const
Return whether another event is a MU-MIMO event that belongs to the same transmission and to the same...
double CalculateChunkSuccessRate(double snir, Time duration, WifiMode mode, const WifiTxVector &txVector, WifiPpduField field) const
Calculate the success rate of the chunk given the SINR, duration, and TXVECTOR.
double CalculatePayloadPer(Ptr< const Event > event, uint16_t channelWidth, NiChangesPerBand *nis, const WifiSpectrumBandInfo &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...
bool HasBand(const WifiSpectrumBandInfo &band) const
Check whether a given band is tracked by this interference helper.
void AddBand(const WifiSpectrumBandInfo &band)
Add a frequency band.
double CalculateNoiseInterferenceW(Ptr< Event > event, NiChangesPerBand &nis, const WifiSpectrumBandInfo &band) const
Calculate noise and interference power in W.
double CalculatePhyHeaderPer(Ptr< const Event > event, NiChangesPerBand *nis, uint16_t channelWidth, const WifiSpectrumBandInfo &band, WifiPpduField header) const
Calculate the error rate of the PHY header.
NiChanges::iterator GetPreviousPosition(Time moment, NiChangesPerBand::iterator niIt)
Returns an iterator to the last NiChange that is before than moment.
void AppendEvent(Ptr< Event > event, const FrequencyRange &freqRange, bool isStartHePortionRxing)
Append the given Event.
double CalculateSnr(Ptr< Event > event, uint16_t channelWidth, uint8_t nss, const WifiSpectrumBandInfo &band) const
Calculate the SNIR for the event (starting from now until the event end).
PhyEntity::SnrPer CalculatePhyHeaderSnrPer(Ptr< Event > event, uint16_t channelWidth, const WifiSpectrumBandInfo &band, WifiPpduField header) const
Calculate the SNIR at the start of the PHY header and accumulate all SNIR changes in the SNIR vector.
static TypeId GetTypeId()
Get the type ID.
void UpdateEvent(Ptr< Event > event, const RxPowerWattPerChannelBand &rxPower)
Update event to scale its received power (W) per band.
void NotifyRxEnd(Time endTime, const FrequencyRange &freqRange)
Notify that RX has ended.
double CalculatePhyHeaderSectionPsr(Ptr< const Event > event, NiChangesPerBand *nis, uint16_t channelWidth, const WifiSpectrumBandInfo &band, PhyEntity::PhyHeaderSections phyHeaderSections) const
Calculate the success rate of the PHY header sections for the provided event.
void SetNumberOfReceiveAntennas(uint8_t rx)
Set the number of RX antennas in the receiver corresponding to this interference helper.
PhyEntity::SnrPer CalculatePayloadSnrPer(Ptr< Event > event, uint16_t channelWidth, const WifiSpectrumBandInfo &band, uint16_t staId, std::pair< Time, Time > relativeMpduStartStop) const
Calculate the SNIR at the start of the payload and accumulate all SNIR changes in the SNIR vector for...
A base class which provides memory management and object aggregation.
Definition: object.h:89
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Definition: phy-entity.h:326
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Control the scheduling of simulation events.
Definition: simulator.h:68
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition: nstime.h:351
@ NS
nanosecond
Definition: nstime.h:119
bool IsZero() const
Exactly equivalent to t == 0.
Definition: nstime.h:315
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Implements the IEEE 802.11 MAC header.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
represent a single transmission mode
Definition: wifi-mode.h:51
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:122
static const Ptr< const PhyEntity > GetStaticPhyEntity(WifiModulationClass modulation)
Get the implemented PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:725
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1522
Class that keeps track of all information about the current PHY operating channel.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
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.
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.
uint16_t GetChannelWidth() const
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:76
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:305
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
WifiPpduField
The type of PPDU field (grouped for convenience)
@ WIFI_PPDU_TYPE_DL_MU
@ WIFI_PPDU_TYPE_UL_MU
@ WIFI_PPDU_FIELD_DATA
data field
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double RatioToDb(double ratio)
Convert from ratio to dB.
Definition: wifi-utils.cc:52
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159
@ WIFI_MAC_QOSDATA
std::map< WifiSpectrumBandInfo, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Definition: phy-entity.h:77
STL namespace.
Struct defining a frequency range between minFrequency (MHz) and maxFrequency (MHz).
uint16_t maxFrequency
the maximum frequency in MHz
uint16_t minFrequency
the minimum frequency in MHz
A struct for both SNR and PER.
Definition: phy-entity.h:147
WifiSpectrumBandInfo structure containing info about a spectrum band.
WifiSpectrumBandFrequencies frequencies
the start and stop frequencies of the band