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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 * Sébastien Deronne <sebastien.deronne@gmail.com>
8 */
9
10#include "interference-helper.h"
11
12#include "error-rate-model.h"
14#include "wifi-phy.h"
15#include "wifi-psdu.h"
16#include "wifi-utils.h"
17
18#include "ns3/he-ppdu.h"
19#include "ns3/log.h"
20#include "ns3/packet.h"
21#include "ns3/simulator.h"
22
23#include <algorithm>
24#include <numeric>
25
26namespace ns3
27{
28
29NS_LOG_COMPONENT_DEFINE("InterferenceHelper");
30
31NS_OBJECT_ENSURE_REGISTERED(InterferenceHelper);
32
33/****************************************************************
34 * PHY event class
35 ****************************************************************/
36
38 : m_ppdu(ppdu),
39 m_startTime(Simulator::Now()),
40 m_endTime(m_startTime + duration),
41 m_rxPowerW(std::move(rxPower))
42{
43}
44
47{
48 return m_ppdu;
49}
50
51Time
53{
54 return m_startTime;
55}
56
57Time
59{
60 return m_endTime;
61}
62
63Time
65{
66 return m_endTime - m_startTime;
67}
68
71{
72 NS_ASSERT(!m_rxPowerW.empty());
73 // The total RX power corresponds to the maximum over all the bands
74 auto it =
75 std::max_element(m_rxPowerW.cbegin(),
76 m_rxPowerW.cend(),
77 [](const auto& p1, const auto& p2) { return p1.second < p2.second; });
78 return it->second;
79}
80
83{
84 const auto it = m_rxPowerW.find(band);
85 NS_ASSERT(it != m_rxPowerW.cend());
86 return it->second;
87}
88
91{
92 return m_rxPowerW;
93}
94
95void
97{
98 NS_ASSERT(rxPower.size() == m_rxPowerW.size());
99 // Update power band per band
100 for (auto& currentRxPowerW : m_rxPowerW)
101 {
102 auto band = currentRxPowerW.first;
103 auto it = rxPower.find(band);
104 if (it != rxPower.end())
105 {
106 currentRxPowerW.second += it->second;
107 }
108 }
109}
110
111void
113{
114 m_ppdu = ppdu;
115}
116
117std::ostream&
118operator<<(std::ostream& os, const Event& event)
119{
120 os << "start=" << event.GetStartTime() << ", end=" << event.GetEndTime()
121 << ", power=" << event.GetRxPower() << "W"
122 << ", PPDU=" << event.GetPpdu();
123 return os;
124}
125
126/****************************************************************
127 * Class which records SNIR change events for a
128 * short period of time.
129 ****************************************************************/
130
132 : m_power(power),
133 m_event(event)
134{
135}
136
138{
139 m_event = nullptr;
140}
141
142Watt_u
144{
145 return m_power;
146}
147
148void
150{
151 m_power += power;
152}
153
156{
157 return m_event;
158}
159
160/****************************************************************
161 * The actual InterferenceHelper
162 ****************************************************************/
163
170
175
176TypeId
178{
179 static TypeId tid = TypeId("ns3::InterferenceHelper")
181 .SetGroupName("Wifi")
182 .AddConstructor<InterferenceHelper>();
183 return tid;
184}
185
186void
188{
189 NS_LOG_FUNCTION(this);
190 for (auto it : m_niChanges)
191 {
192 it.second.clear();
193 }
194 m_niChanges.clear();
195 m_firstPowers.clear();
196 m_errorRateModel = nullptr;
197}
198
201 Time duration,
203 const FrequencyRange& freqRange,
204 bool isStartHePortionRxing)
205{
206 Ptr<Event> event = Create<Event>(ppdu, duration, std::move(rxPowerW));
207 AppendEvent(event, freqRange, isStartHePortionRxing);
208 return event;
209}
210
211void
214 const FrequencyRange& freqRange)
215{
216 // Parameters other than duration and rxPowerW are unused for this type
217 // of signal, so we provide dummy versions
218 WifiMacHeader hdr;
220 hdr.SetQosTid(0);
222 WifiTxVector(),
224 Add(fakePpdu, duration, rxPowerW, freqRange);
225}
226
227bool
229{
230 return !m_niChanges.empty();
231}
232
233bool
235{
236 return m_niChanges.contains(band);
237}
238
239void
241{
242 NS_LOG_FUNCTION(this << band);
243 NS_ASSERT(!m_niChanges.contains(band));
244 NS_ASSERT(!m_firstPowers.contains(band));
245 NiChanges niChanges;
246 auto result = m_niChanges.insert({band, niChanges});
247 NS_ASSERT(result.second);
248 // Always have a zero power noise event in the list
249 AddNiChangeEvent(Time(0), NiChange(0.0, nullptr), result.first);
250 m_firstPowers.insert({band, 0.0});
251}
252
253void
255{
256 NS_LOG_FUNCTION(this << band);
257 NS_ASSERT(m_firstPowers.count(band) != 0);
258 m_firstPowers.erase(band);
259 auto it = m_niChanges.find(band);
260 NS_ASSERT(it != std::end(m_niChanges));
261 it->second.clear();
262 m_niChanges.erase(it);
263}
264
265void
266InterferenceHelper::UpdateBands(const std::vector<WifiSpectrumBandInfo>& bands,
267 const FrequencyRange& freqRange)
268{
269 NS_LOG_FUNCTION(this << freqRange);
270 std::vector<WifiSpectrumBandInfo> bandsToRemove{};
271 for (auto it = m_niChanges.begin(); it != m_niChanges.end(); ++it)
272 {
273 if (!IsBandInFrequencyRange(it->first, freqRange))
274 {
275 continue;
276 }
277 const auto frequencies = it->first.frequencies;
278 const auto found =
279 std::find_if(bands.cbegin(), bands.cend(), [frequencies](const auto& item) {
280 return frequencies == item.frequencies;
281 }) != std::end(bands);
282 if (!found)
283 {
284 // band does not belong to the new bands, erase it
285 bandsToRemove.emplace_back(it->first);
286 }
287 }
288 for (const auto& band : bandsToRemove)
289 {
290 RemoveBand(band);
291 }
292 for (const auto& band : bands)
293 {
294 if (!HasBand(band))
295 {
296 // this is a new band, add it
297 AddBand(band);
298 }
299 }
300}
301
302void
304{
305 m_noiseFigure = value;
306}
307
308void
319
320void
325
326Time
328{
329 NS_LOG_FUNCTION(this << energy << band);
330 Time now = Simulator::Now();
331 auto niIt = m_niChanges.find(band);
332 NS_ABORT_IF(niIt == m_niChanges.end());
333 auto i = GetPreviousPosition(now, niIt);
334 Time end = i->first;
335 for (; i != niIt->second.end(); ++i)
336 {
337 const auto noiseInterference = i->second.GetPower();
338 end = i->first;
339 if (noiseInterference < energy)
340 {
341 break;
342 }
343 }
344 return end > now ? end - now : Time{0};
345}
347void
349 const FrequencyRange& freqRange,
350 bool isStartHePortionRxing)
351{
352 NS_LOG_FUNCTION(this << event << freqRange << isStartHePortionRxing);
353 for (const auto& [band, power] : event->GetRxPowerPerBand())
354 {
355 auto niIt = m_niChanges.find(band);
356 NS_ABORT_IF(niIt == m_niChanges.end());
357 Watt_u previousPowerStart = 0;
358 Watt_u previousPowerEnd = 0;
359 auto previousPowerPosition = GetPreviousPosition(event->GetStartTime(), niIt);
360 previousPowerStart = previousPowerPosition->second.GetPower();
361 previousPowerEnd = GetPreviousPosition(event->GetEndTime(), niIt)->second.GetPower();
362 if (const auto rxing = (m_rxing.contains(freqRange) && m_rxing.at(freqRange)); !rxing)
363 {
364 m_firstPowers.find(band)->second = previousPowerStart;
365 // Always leave the first zero power noise event in the list
366 niIt->second.erase(++(niIt->second.begin()), ++previousPowerPosition);
367 }
368 else if (isStartHePortionRxing)
369 {
370 // When the first HE portion is received, we need to set m_firstPowerPerBand
371 // so that it takes into account interferences that arrived between the start of the
372 // HE TB PPDU transmission and the start of HE TB payload.
373 m_firstPowers.find(band)->second = previousPowerStart;
374 }
375 auto first =
376 AddNiChangeEvent(event->GetStartTime(), NiChange(previousPowerStart, event), niIt);
377 auto last = AddNiChangeEvent(event->GetEndTime(), NiChange(previousPowerEnd, event), niIt);
378 for (auto i = first; i != last; ++i)
379 {
380 i->second.AddPower(power);
381 }
382 }
383}
384
385void
387{
388 NS_LOG_FUNCTION(this << event);
389 // This is called for UL MU events, in order to scale power as long as UL MU PPDUs arrive
390 for (const auto& [band, power] : rxPower)
391 {
392 auto niIt = m_niChanges.find(band);
393 NS_ABORT_IF(niIt == m_niChanges.end());
394 auto first = GetPreviousPosition(event->GetStartTime(), niIt);
395 auto last = GetPreviousPosition(event->GetEndTime(), niIt);
396 for (auto i = first; i != last; ++i)
397 {
398 i->second.AddPower(power);
399 }
400 }
401 event->UpdateRxPowerW(rxPower);
402}
403
404double
406 Watt_u noiseInterference,
407 MHz_u channelWidth,
408 uint8_t nss) const
409{
410 NS_LOG_FUNCTION(this << signal << noiseInterference << channelWidth << +nss);
411 // thermal noise at 290K in J/s = W
412 static const double BOLTZMANN = 1.3803e-23;
413 // Nt is the power of thermal noise in W
414 const auto Nt = BOLTZMANN * 290 * channelWidth * 1e6;
415 // receiver noise Floor which accounts for thermal noise and non-idealities of the receiver
416 Watt_u noiseFloor = m_noiseFigure * Nt;
417 Watt_u noise = noiseFloor + noiseInterference;
418 auto snr = signal / noise; // linear scale
419 NS_LOG_DEBUG("bandwidth=" << channelWidth << "MHz, signal=" << signal << "W, noise="
420 << noiseFloor << "W, interference=" << noiseInterference
421 << "W, snr=" << RatioToDb(snr) << "dB");
422 if (m_errorRateModel->IsAwgn())
423 {
424 double gain = 1;
425 if (m_numRxAntennas > nss)
426 {
427 gain = static_cast<double>(m_numRxAntennas) /
428 nss; // compute gain offered by diversity for AWGN
429 }
430 NS_LOG_DEBUG("SNR improvement thanks to diversity: " << 10 * std::log10(gain) << "dB");
431 snr *= gain;
432 }
433 return snr;
434}
435
436Watt_u
438 NiChangesPerBand& nis,
439 const WifiSpectrumBandInfo& band) const
440{
441 NS_LOG_FUNCTION(this << band);
442 auto firstPower_it = m_firstPowers.find(band);
443 NS_ABORT_IF(firstPower_it == m_firstPowers.end());
444 auto noiseInterference = firstPower_it->second;
445 auto niIt = m_niChanges.find(band);
446 NS_ABORT_IF(niIt == m_niChanges.end());
447 const auto now = Simulator::Now();
448 auto it = niIt->second.find(event->GetStartTime());
449 const auto muMimoPower = (event->GetPpdu()->GetType() == WIFI_PPDU_TYPE_UL_MU)
450 ? CalculateMuMimoPowerW(event, band)
451 : 0.0;
452 for (; it != niIt->second.end() && it->first < now; ++it)
453 {
454 if (IsSameMuMimoTransmission(event, it->second.GetEvent()) &&
455 (event != it->second.GetEvent()))
456 {
457 // Do not calculate noiseInterferenceW if events belong to the same MU-MIMO transmission
458 // unless this is the same event
459 continue;
460 }
461 noiseInterference = it->second.GetPower() - event->GetRxPower(band) - muMimoPower;
462 if (std::abs(noiseInterference) < std::numeric_limits<double>::epsilon())
463 {
464 // fix some possible rounding issues with double values
465 noiseInterference = 0.0;
466 }
467 }
468 it = niIt->second.find(event->GetStartTime());
469 NS_ABORT_IF(it == niIt->second.end());
470 for (; it != niIt->second.end() && it->second.GetEvent() != event; ++it)
471 {
472 ;
473 }
474 NiChanges ni;
475 ni.emplace(event->GetStartTime(), NiChange(0, event));
476 while (++it != niIt->second.end() && it->second.GetEvent() != event)
477 {
478 ni.insert(*it);
479 }
480 ni.emplace(event->GetEndTime(), NiChange(0, event));
481 nis.insert({band, ni});
482 NS_ASSERT_MSG(noiseInterference >= 0.0,
483 "CalculateNoiseInterferenceW returns negative value " << noiseInterference);
484 return noiseInterference;
485}
486
487Watt_u
489 const WifiSpectrumBandInfo& band) const
490{
491 auto niIt = m_niChanges.find(band);
492 NS_ASSERT(niIt != m_niChanges.end());
493 auto it = niIt->second.begin();
494 ++it;
495 Watt_u muMimoPower{0.0};
496 for (; it != niIt->second.end() && it->first < Simulator::Now(); ++it)
497 {
498 if (IsSameMuMimoTransmission(event, it->second.GetEvent()))
499 {
500 auto hePpdu = DynamicCast<HePpdu>(it->second.GetEvent()->GetPpdu()->Copy());
501 NS_ASSERT(hePpdu);
502 HePpdu::TxPsdFlag psdFlag = hePpdu->GetTxPsdFlag();
503 if (psdFlag == HePpdu::PSD_HE_PORTION)
504 {
505 const auto staId =
506 event->GetPpdu()->GetTxVector().GetHeMuUserInfoMap().cbegin()->first;
507 const auto otherStaId = it->second.GetEvent()
508 ->GetPpdu()
509 ->GetTxVector()
510 .GetHeMuUserInfoMap()
511 .cbegin()
512 ->first;
513 if (staId == otherStaId)
514 {
515 break;
516 }
517 muMimoPower += it->second.GetEvent()->GetRxPower(band);
518 }
519 }
520 }
521 return muMimoPower;
522}
523
524double
526 Time duration,
527 WifiMode mode,
528 const WifiTxVector& txVector,
529 WifiPpduField field) const
530{
531 if (duration.IsZero())
532 {
533 return 1.0;
534 }
535 const auto rate = mode.GetDataRate(txVector.GetChannelWidth());
536 auto nbits = static_cast<uint64_t>(rate * duration.GetSeconds());
537 const auto csr =
538 m_errorRateModel->GetChunkSuccessRate(mode, txVector, snir, nbits, m_numRxAntennas, field);
539 return csr;
540}
541
542double
544 Time duration,
545 const WifiTxVector& txVector,
546 uint16_t staId) const
547{
548 if (duration.IsZero())
549 {
550 return 1.0;
551 }
552 const auto mode = txVector.GetMode(staId);
553 const auto rate = mode.GetDataRate(txVector, staId);
554 auto nbits = static_cast<uint64_t>(rate * duration.GetSeconds());
555 nbits /= txVector.GetNss(staId); // divide effective number of bits by NSS to achieve same chunk
556 // error rate as SISO for AWGN
557 double csr = m_errorRateModel->GetChunkSuccessRate(mode,
558 txVector,
559 snir,
560 nbits,
563 staId);
564 return csr;
565}
566
567double
569 MHz_u channelWidth,
570 NiChangesPerBand* nis,
571 const WifiSpectrumBandInfo& band,
572 uint16_t staId,
573 std::pair<Time, Time> window) const
574{
575 NS_LOG_FUNCTION(this << channelWidth << band << staId << window.first << window.second);
576 double psr = 1.0; /* Packet Success Rate */
577 const auto& niIt = nis->find(band)->second;
578 auto j = niIt.cbegin();
579 auto previous = j->first;
580 Watt_u muMimoPower = 0.0;
581 const auto payloadMode = event->GetPpdu()->GetTxVector().GetMode(staId);
582 auto phyPayloadStart = j->first;
583 if (event->GetPpdu()->GetType() != WIFI_PPDU_TYPE_UL_MU &&
584 event->GetPpdu()->GetType() !=
585 WIFI_PPDU_TYPE_DL_MU) // j->first corresponds to the start of the MU payload
586 {
587 phyPayloadStart = j->first + WifiPhy::CalculatePhyPreambleAndHeaderDuration(
588 event->GetPpdu()->GetTxVector());
589 }
590 else
591 {
592 muMimoPower = CalculateMuMimoPowerW(event, band);
593 }
594 const auto windowStart = phyPayloadStart + window.first;
595 const auto windowEnd = phyPayloadStart + window.second;
596 NS_ABORT_IF(!m_firstPowers.contains(band));
597 auto noiseInterference = m_firstPowers.at(band);
598 auto power = event->GetRxPower(band);
599 while (++j != niIt.cend())
600 {
601 Time current = j->first;
602 NS_LOG_DEBUG("previous= " << previous << ", current=" << current);
603 NS_ASSERT(current >= previous);
604 const auto snr = CalculateSnr(power,
605 noiseInterference,
606 channelWidth,
607 event->GetPpdu()->GetTxVector().GetNss(staId));
608 // Case 1: Both previous and current point to the windowed payload
609 if (previous >= windowStart)
610 {
612 Min(windowEnd, current) - previous,
613 event->GetPpdu()->GetTxVector(),
614 staId);
615 NS_LOG_DEBUG("Both previous and current point to the windowed payload: mode="
616 << payloadMode << ", psr=" << psr);
617 }
618 // Case 2: previous is before windowed payload and current is in the windowed payload
619 else if (current >= windowStart)
620 {
622 Min(windowEnd, current) - windowStart,
623 event->GetPpdu()->GetTxVector(),
624 staId);
626 "previous is before windowed payload and current is in the windowed payload: mode="
627 << payloadMode << ", psr=" << psr);
628 }
629 noiseInterference = j->second.GetPower() - power;
630 if (IsSameMuMimoTransmission(event, j->second.GetEvent()))
631 {
632 muMimoPower += j->second.GetEvent()->GetRxPower(band);
633 NS_LOG_DEBUG("PPDU belongs to same MU-MIMO transmission: muMimoPowerW=" << muMimoPower);
634 }
635 noiseInterference -= muMimoPower;
636 previous = j->first;
637 if (previous > windowEnd)
638 {
639 NS_LOG_DEBUG("Stop: new previous=" << previous
640 << " after time window end=" << windowEnd);
641 break;
642 }
643 }
644 const auto per = 1.0 - psr;
645 return per;
646}
647
648double
650 Ptr<const Event> event,
651 NiChangesPerBand* nis,
652 MHz_u channelWidth,
653 const WifiSpectrumBandInfo& band,
654 PhyEntity::PhyHeaderSections phyHeaderSections) const
655{
656 NS_LOG_FUNCTION(this << band);
657 double psr = 1.0; /* Packet Success Rate */
658 auto niIt = nis->find(band)->second;
659 auto j = niIt.begin();
660
661 NS_ASSERT(!phyHeaderSections.empty());
662 Time stopLastSection;
663 for (const auto& section : phyHeaderSections)
664 {
665 stopLastSection = Max(stopLastSection, section.second.first.second);
666 }
667
668 auto previous = j->first;
669 NS_ABORT_IF(!m_firstPowers.contains(band));
670 auto noiseInterference = m_firstPowers.at(band);
671 const auto power = event->GetRxPower(band);
672 while (++j != niIt.end())
673 {
674 auto current = j->first;
675 NS_LOG_DEBUG("previous= " << previous << ", current=" << current);
676 NS_ASSERT(current >= previous);
677 const auto snr = CalculateSnr(power, noiseInterference, channelWidth, 1);
678 for (const auto& section : phyHeaderSections)
679 {
680 const auto start = section.second.first.first;
681 const auto stop = section.second.first.second;
682
683 if (previous <= stop || current >= start)
684 {
685 const auto duration = Min(stop, current) - Max(start, previous);
686 if (duration.IsStrictlyPositive())
687 {
688 psr *= CalculateChunkSuccessRate(snr,
689 duration,
690 section.second.second,
691 event->GetPpdu()->GetTxVector(),
692 section.first);
693 NS_LOG_DEBUG("Current NI change in "
694 << section.first << " [" << start << ", " << stop << "] for "
695 << duration.As(Time::NS) << ": mode=" << section.second.second
696 << ", psr=" << psr);
697 }
698 }
699 }
700 noiseInterference = j->second.GetPower() - power;
701 previous = j->first;
702 if (previous > stopLastSection)
703 {
704 NS_LOG_DEBUG("Stop: new previous=" << previous << " after stop of last section="
705 << stopLastSection);
706 break;
707 }
708 }
709 return psr;
710}
711
712double
714 NiChangesPerBand* nis,
715 MHz_u channelWidth,
716 const WifiSpectrumBandInfo& band,
717 WifiPpduField header) const
718{
719 NS_LOG_FUNCTION(this << band << header);
720 auto niIt = nis->find(band)->second;
721 auto phyEntity =
722 WifiPhy::GetStaticPhyEntity(event->GetPpdu()->GetTxVector().GetModulationClass());
723
725 for (const auto& section :
726 phyEntity->GetPhyHeaderSections(event->GetPpdu()->GetTxVector(), niIt.begin()->first))
727 {
728 if (section.first == header)
729 {
730 sections[header] = section.second;
731 }
732 }
733
734 double psr = 1.0;
735 if (!sections.empty())
736 {
737 psr = CalculatePhyHeaderSectionPsr(event, nis, channelWidth, band, sections);
738 }
739 return 1 - psr;
740}
741
744 MHz_u channelWidth,
745 const WifiSpectrumBandInfo& band,
746 uint16_t staId,
747 std::pair<Time, Time> relativeMpduStartStop) const
748{
749 NS_LOG_FUNCTION(this << channelWidth << band << staId << relativeMpduStartStop.first
750 << relativeMpduStartStop.second);
752 const auto noiseInterference = CalculateNoiseInterferenceW(event, ni, band);
753 const auto snr = CalculateSnr(event->GetRxPower(band),
754 noiseInterference,
755 channelWidth,
756 event->GetPpdu()->GetTxVector().GetNss(staId));
757
758 /* calculate the SNIR at the start of the MPDU (located through windowing) and accumulate
759 * all SNIR changes in the SNIR vector.
760 */
761 const auto per =
762 CalculatePayloadPer(event, channelWidth, &ni, band, staId, relativeMpduStartStop);
763
764 return PhyEntity::SnrPer(snr, per);
765}
766
767double
769 MHz_u channelWidth,
770 uint8_t nss,
771 const WifiSpectrumBandInfo& band) const
772{
774 const auto noiseInterference = CalculateNoiseInterferenceW(event, ni, band);
775 return CalculateSnr(event->GetRxPower(band), noiseInterference, channelWidth, nss);
776}
777
780 MHz_u channelWidth,
781 const WifiSpectrumBandInfo& band,
782 WifiPpduField header) const
783{
784 NS_LOG_FUNCTION(this << band << header);
786 const auto noiseInterference = CalculateNoiseInterferenceW(event, ni, band);
787 const auto snr = CalculateSnr(event->GetRxPower(band), noiseInterference, channelWidth, 1);
788
789 /* calculate the SNIR at the start of the PHY header and accumulate
790 * all SNIR changes in the SNIR vector.
791 */
792 const auto per = CalculatePhyHeaderPer(event, &ni, channelWidth, band, header);
793
794 return PhyEntity::SnrPer(snr, per);
795}
796
797InterferenceHelper::NiChanges::iterator
798InterferenceHelper::GetNextPosition(Time moment, NiChangesPerBand::iterator niIt)
799{
800 return niIt->second.upper_bound(moment);
801}
802
803InterferenceHelper::NiChanges::iterator
804InterferenceHelper::GetPreviousPosition(Time moment, NiChangesPerBand::iterator niIt)
805{
806 auto it = GetNextPosition(moment, niIt);
807 // This is safe since there is always an NiChange at time 0,
808 // before moment.
809 --it;
810 return it;
811}
812
813InterferenceHelper::NiChanges::iterator
814InterferenceHelper::AddNiChangeEvent(Time moment, NiChange change, NiChangesPerBand::iterator niIt)
815{
816 return niIt->second.insert(GetNextPosition(moment, niIt), {moment, change});
817}
818
819void
821{
822 NS_LOG_FUNCTION(this << freqRange);
823 m_rxing[freqRange] = true;
824}
825
826void
828{
829 NS_LOG_FUNCTION(this << endTime << freqRange);
830 m_rxing.at(freqRange) = false;
831 // Update m_firstPowers for frame capture
832 for (auto niIt = m_niChanges.begin(); niIt != m_niChanges.end(); ++niIt)
833 {
834 if (!IsBandInFrequencyRange(niIt->first, freqRange))
835 {
836 continue;
837 }
838 NS_ASSERT(niIt->second.size() > 1);
839 auto it = GetPreviousPosition(endTime, niIt);
840 it--;
841 m_firstPowers.find(niIt->first)->second = it->second.GetPower();
842 }
843}
844
845bool
847 const FrequencyRange& freqRange) const
848{
849 return std::all_of(band.frequencies.cbegin(),
850 band.frequencies.cend(),
851 [&freqRange](const auto& freqs) {
852 return ((freqs.second > (freqRange.minFrequency * 1e6)) &&
853 (freqs.first < (freqRange.maxFrequency * 1e6)));
854 });
855}
856
857bool
859 Ptr<const Event> otherEvent) const
860{
861 if ((currentEvent->GetPpdu()->GetType() == WIFI_PPDU_TYPE_UL_MU) &&
862 (otherEvent->GetPpdu()->GetType() == WIFI_PPDU_TYPE_UL_MU) &&
863 (currentEvent->GetPpdu()->GetUid() == otherEvent->GetPpdu()->GetUid()))
864 {
865 const auto currentTxVector = currentEvent->GetPpdu()->GetTxVector();
866 const auto otherTxVector = otherEvent->GetPpdu()->GetTxVector();
867 NS_ASSERT(currentTxVector.GetHeMuUserInfoMap().size() == 1);
868 NS_ASSERT(otherTxVector.GetHeMuUserInfoMap().size() == 1);
869 const auto currentUserInfo = currentTxVector.GetHeMuUserInfoMap().cbegin();
870 const auto otherUserInfo = otherTxVector.GetHeMuUserInfoMap().cbegin();
871 return (currentUserInfo->second.ru == otherUserInfo->second.ru);
872 }
873 return false;
874}
875
876} // namespace ns3
#define Max(a, b)
#define Min(a, b)
handles interference calculations
Time m_endTime
end time
Watt_u GetRxPower() const
Return the total received power.
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.
const RxPowerWattPerChannelBand & GetRxPowerPerBand() const
Return the received power (W) for all bands.
RxPowerWattPerChannelBand m_rxPowerW
received power in watts per band
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:104
@ PSD_HE_PORTION
HE portion of an HE PPDU.
Definition he-ppdu.h:106
Noise and Interference (thus Ni) event.
void AddPower(Watt_u power)
Add a given amount of power.
NiChange(Watt_u power, Ptr< Event > event)
Create a NiChange at the given time and the amount of NI change.
Watt_u GetPower() const
Return the power.
Ptr< Event > GetEvent() const
Return the event causes the corresponding NI change.
handles interference calculations
double CalculatePhyHeaderPer(Ptr< const Event > event, NiChangesPerBand *nis, MHz_u channelWidth, const WifiSpectrumBandInfo &band, WifiPpduField header) const
Calculate the error rate of the PHY header.
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.
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
Time GetEnergyDuration(Watt_u energy, const WifiSpectrumBandInfo &band)
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.
PhyEntity::SnrPer CalculatePayloadSnrPer(Ptr< Event > event, MHz_u 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...
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
double CalculatePhyHeaderSectionPsr(Ptr< const Event > event, NiChangesPerBand *nis, MHz_u channelWidth, const WifiSpectrumBandInfo &band, PhyEntity::PhyHeaderSections phyHeaderSections) const
Calculate the success rate of the PHY header sections for the provided event.
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
PhyEntity::SnrPer CalculatePhyHeaderSnrPer(Ptr< Event > event, MHz_u 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.
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.
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.
Watt_u 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...
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.
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 RemoveBand(const WifiSpectrumBandInfo &band)
Remove a frequency band.
void NotifyRxEnd(Time endTime, const FrequencyRange &freqRange)
Notify that RX has ended.
Watt_u CalculateNoiseInterferenceW(Ptr< Event > event, NiChangesPerBand &nis, const WifiSpectrumBandInfo &band) const
Calculate noise and interference power.
void SetNumberOfReceiveAntennas(uint8_t rx)
Set the number of RX antennas in the receiver corresponding to this interference helper.
double CalculateSnr(Ptr< Event > event, MHz_u channelWidth, uint8_t nss, const WifiSpectrumBandInfo &band) const
Calculate the SNIR for the event (starting from now until the event end).
double CalculatePayloadPer(Ptr< const Event > event, MHz_u 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...
A base class which provides memory management and object aggregation.
Definition object.h:78
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Definition phy-entity.h:294
Smart pointer class similar to boost::intrusive_ptr.
Control the scheduling of simulation events.
Definition simulator.h:57
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
@ NS
nanosecond
Definition nstime.h:108
bool IsZero() const
Exactly equivalent to t == 0.
Definition nstime.h:304
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
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:40
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:111
static const Ptr< const PhyEntity > GetStaticPhyEntity(WifiModulationClass modulation)
Get the implemented PHY entity corresponding to the modulation class.
Definition wifi-phy.cc:745
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition wifi-phy.cc:1565
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.
MHz_u 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:55
#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:75
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition simulator.cc:294
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.
dB_u RatioToDb(double ratio)
Convert from ratio to dB.
Definition wifi-utils.cc:44
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
std::map< WifiSpectrumBandInfo, Watt_u > RxPowerWattPerChannelBand
A map of the received power for each band.
Definition phy-entity.h:45
@ WIFI_MAC_QOSDATA
double Watt_u
Watt weak type.
Definition wifi-units.h:25
STL namespace.
Struct defining a frequency range between minFrequency and maxFrequency.
A struct for both SNR and PER.
Definition phy-entity.h:115
WifiSpectrumBandInfo structure containing info about a spectrum band.
std::vector< WifiSpectrumBandFrequencies > frequencies
the start and stop frequencies for each segment of the band