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
137Watt_u
139{
140 return m_power;
141}
142
143void
145{
146 m_power += power;
147}
148
151{
152 return m_event;
153}
154
155/****************************************************************
156 * The actual InterferenceHelper
157 ****************************************************************/
158
165
170
171TypeId
173{
174 static TypeId tid = TypeId("ns3::InterferenceHelper")
176 .SetGroupName("Wifi")
177 .AddConstructor<InterferenceHelper>();
178 return tid;
179}
180
181void
183{
184 NS_LOG_FUNCTION(this);
185 for (auto it : m_niChanges)
186 {
187 it.second.clear();
188 }
189 m_niChanges.clear();
190 m_firstPowers.clear();
191 m_errorRateModel = nullptr;
192}
193
196 Time duration,
198 const FrequencyRange& freqRange,
199 bool isStartHePortionRxing)
200{
201 Ptr<Event> event = Create<Event>(ppdu, duration, std::move(rxPowerW));
202 AppendEvent(event, freqRange, isStartHePortionRxing);
203 return event;
204}
205
206void
209 const FrequencyRange& freqRange)
210{
211 // Parameters other than duration and rxPowerW are unused for this type
212 // of signal, so we provide dummy versions
213 WifiMacHeader hdr;
215 hdr.SetQosTid(0);
217 WifiTxVector(),
219 Add(fakePpdu, duration, rxPowerW, freqRange);
220}
221
222bool
224{
225 return !m_niChanges.empty();
226}
227
228bool
230{
231 return m_niChanges.contains(band);
232}
233
234void
236{
237 NS_LOG_FUNCTION(this << band);
238 NS_ASSERT(!m_niChanges.contains(band));
239 NS_ASSERT(!m_firstPowers.contains(band));
240 NiChanges niChanges;
241 auto result = m_niChanges.insert({band, niChanges});
242 NS_ASSERT(result.second);
243 // Always have a zero power noise event in the list
244 AddNiChangeEvent(Time(0), NiChange(Watt_u{0}, nullptr), result.first);
245 m_firstPowers.insert({band, Watt_u{0}});
246}
247
248void
250{
251 NS_LOG_FUNCTION(this << band);
252 NS_ASSERT(m_firstPowers.count(band) != 0);
253 m_firstPowers.erase(band);
254 auto it = m_niChanges.find(band);
255 NS_ASSERT(it != std::end(m_niChanges));
256 it->second.clear();
257 m_niChanges.erase(it);
258}
260void
261InterferenceHelper::UpdateBands(const std::vector<WifiSpectrumBandInfo>& bands,
262 const FrequencyRange& freqRange)
263{
264 NS_LOG_FUNCTION(this << freqRange);
265 std::vector<WifiSpectrumBandInfo> bandsToRemove{};
266 for (auto it = m_niChanges.begin(); it != m_niChanges.end(); ++it)
267 {
268 if (!IsBandInFrequencyRange(it->first, freqRange))
269 {
270 continue;
271 }
272 const auto frequencies = it->first.frequencies;
273 const auto found =
274 std::find_if(bands.cbegin(), bands.cend(), [frequencies](const auto& item) {
275 return frequencies == item.frequencies;
276 }) != std::end(bands);
277 if (!found)
278 {
279 // band does not belong to the new bands, erase it
280 bandsToRemove.emplace_back(it->first);
281 }
282 }
283 for (const auto& band : bandsToRemove)
284 {
285 RemoveBand(band);
286 }
287 for (const auto& band : bands)
288 {
289 if (!HasBand(band))
290 {
291 // this is a new band, add it
292 AddBand(band);
293 }
294 }
295}
296
297void
299{
300 m_noiseFigure = value;
301}
302
303void
308
314
315void
320
321Time
323{
324 NS_LOG_FUNCTION(this << energy << band);
325 Time now = Simulator::Now();
326 auto niIt = m_niChanges.find(band);
327 NS_ABORT_IF(niIt == m_niChanges.end());
328 auto i = GetPreviousPosition(now, niIt);
329 Time end = i->first;
330 for (; i != niIt->second.end(); ++i)
331 {
332 const auto noiseInterference = i->second.GetPower();
333 end = i->first;
334 if (noiseInterference < energy)
335 {
336 break;
337 }
338 }
339 return end > now ? end - now : Time{0};
340}
341
342void
344 const FrequencyRange& freqRange,
345 bool isStartHePortionRxing)
347 NS_LOG_FUNCTION(this << event << freqRange << isStartHePortionRxing);
348 for (const auto& [band, power] : event->GetRxPowerPerBand())
349 {
350 auto niIt = m_niChanges.find(band);
351 NS_ABORT_IF(niIt == m_niChanges.end());
352 Watt_u previousPowerStart{0.0};
353 Watt_u previousPowerEnd{0.0};
354 auto previousPowerPosition = GetPreviousPosition(event->GetStartTime(), niIt);
355 previousPowerStart = previousPowerPosition->second.GetPower();
356 previousPowerEnd = GetPreviousPosition(event->GetEndTime(), niIt)->second.GetPower();
357 if (const auto rxing = (m_rxing.contains(freqRange) && m_rxing.at(freqRange)); !rxing)
358 {
359 m_firstPowers.find(band)->second = previousPowerStart;
360 // Always leave the first zero power noise event in the list
361 niIt->second.erase(++(niIt->second.begin()), ++previousPowerPosition);
362 }
363 else if (isStartHePortionRxing)
364 {
365 // When the first HE portion is received, we need to set m_firstPowerPerBand
366 // so that it takes into account interferences that arrived between the start of the
367 // HE TB PPDU transmission and the start of HE TB payload.
368 m_firstPowers.find(band)->second = previousPowerStart;
369 }
370 auto first =
371 AddNiChangeEvent(event->GetStartTime(), NiChange(previousPowerStart, event), niIt);
372 auto last = AddNiChangeEvent(event->GetEndTime(), NiChange(previousPowerEnd, event), niIt);
373 for (auto i = first; i != last; ++i)
374 {
375 i->second.AddPower(power);
376 }
377 }
378}
379
380void
382{
383 NS_LOG_FUNCTION(this << event);
384 // This is called for UL MU events, in order to scale power as long as UL MU PPDUs arrive
385 for (const auto& [band, power] : rxPower)
386 {
387 auto niIt = m_niChanges.find(band);
388 NS_ABORT_IF(niIt == m_niChanges.end());
389 auto first = GetPreviousPosition(event->GetStartTime(), niIt);
390 auto last = GetPreviousPosition(event->GetEndTime(), niIt);
391 for (auto i = first; i != last; ++i)
392 {
393 i->second.AddPower(power);
394 }
395 }
396 event->UpdateRxPowerW(rxPower);
397}
398
399double
401 Watt_u noiseInterference,
402 MHz_u channelWidth,
403 uint8_t nss) const
404{
405 NS_LOG_FUNCTION(this << signal << noiseInterference << channelWidth << +nss);
406 // thermal noise at 290K in J/s = W
407 static const double BOLTZMANN = 1.3803e-23;
408 // Nt is the power of thermal noise in W
409 const auto Nt = BOLTZMANN * 290 * MHzToHz(channelWidth);
410 // receiver noise Floor which accounts for thermal noise and non-idealities of the receiver
411 Watt_u noiseFloor{m_noiseFigure * Nt};
412 Watt_u noise = noiseFloor + noiseInterference;
413 auto snr = signal / noise; // linear scale
414 NS_LOG_DEBUG("bandwidth=" << channelWidth << "MHz, signal=" << signal << "W, noise="
415 << noiseFloor << "W, interference=" << noiseInterference
416 << "W, snr=" << RatioToDb(snr) << "dB");
417 if (m_errorRateModel->IsAwgn())
418 {
419 double gain = 1;
420 if (m_numRxAntennas > nss)
421 {
422 gain = static_cast<double>(m_numRxAntennas) /
423 nss; // compute gain offered by diversity for AWGN
424 }
425 NS_LOG_DEBUG("SNR improvement thanks to diversity: " << 10 * std::log10(gain) << "dB");
426 snr *= gain;
427 }
428 return snr;
429}
430
431Watt_u
433 NiChangesPerBand& nis,
434 const WifiSpectrumBandInfo& band) const
435{
436 NS_LOG_FUNCTION(this << band);
437 auto firstPower_it = m_firstPowers.find(band);
438 NS_ABORT_IF(firstPower_it == m_firstPowers.end());
439 auto noiseInterference = firstPower_it->second;
440 auto niIt = m_niChanges.find(band);
441 NS_ABORT_IF(niIt == m_niChanges.end());
442 const auto now = Simulator::Now();
443 auto it = niIt->second.find(event->GetStartTime());
444 const auto muMimoPower = (event->GetPpdu()->GetType() == WIFI_PPDU_TYPE_UL_MU)
445 ? CalculateMuMimoPowerW(event, band)
446 : Watt_u{0.0};
447 for (; it != niIt->second.end() && it->first < now; ++it)
448 {
449 if (IsSameMuMimoTransmission(event, it->second.GetEvent()) &&
450 (event != it->second.GetEvent()))
451 {
452 // Do not calculate noiseInterferenceW if events belong to the same MU-MIMO transmission
453 // unless this is the same event
454 continue;
455 }
456 noiseInterference = it->second.GetPower() - event->GetRxPower(band) - muMimoPower;
457 if (std::abs(noiseInterference) < std::numeric_limits<double>::epsilon())
458 {
459 // fix some possible rounding issues with double values
460 noiseInterference = Watt_u{0.0};
461 }
462 }
463 it = niIt->second.find(event->GetStartTime());
464 NS_ABORT_IF(it == niIt->second.end());
465 for (; it != niIt->second.end() && it->second.GetEvent() != event; ++it)
466 {
467 ;
468 }
469 NiChanges ni;
470 ni.emplace(event->GetStartTime(), NiChange(Watt_u{0}, event));
471 while (++it != niIt->second.end() && it->second.GetEvent() != event)
472 {
473 ni.insert(*it);
474 }
475 ni.emplace(event->GetEndTime(), NiChange(Watt_u{0}, event));
476 nis.insert({band, ni});
477 NS_ASSERT_MSG(noiseInterference >= Watt_u{0.0},
478 "CalculateNoiseInterferenceW returns negative value " << noiseInterference);
479 return noiseInterference;
480}
481
482Watt_u
484 const WifiSpectrumBandInfo& band) const
485{
486 auto niIt = m_niChanges.find(band);
487 NS_ASSERT(niIt != m_niChanges.end());
488 auto it = niIt->second.begin();
489 ++it;
490 Watt_u muMimoPower{0.0};
491 for (; it != niIt->second.end() && it->first < Simulator::Now(); ++it)
492 {
493 if (IsSameMuMimoTransmission(event, it->second.GetEvent()))
494 {
495 auto hePpdu = DynamicCast<HePpdu>(it->second.GetEvent()->GetPpdu()->Copy());
496 NS_ASSERT(hePpdu);
497 HePpdu::TxPsdFlag psdFlag = hePpdu->GetTxPsdFlag();
498 if (psdFlag == HePpdu::PSD_HE_PORTION)
499 {
500 const auto staId =
501 event->GetPpdu()->GetTxVector().GetHeMuUserInfoMap().cbegin()->first;
502 const auto otherStaId = it->second.GetEvent()
503 ->GetPpdu()
504 ->GetTxVector()
505 .GetHeMuUserInfoMap()
506 .cbegin()
507 ->first;
508 if (staId == otherStaId)
509 {
510 break;
511 }
512 muMimoPower += it->second.GetEvent()->GetRxPower(band);
513 }
514 }
515 }
516 return muMimoPower;
517}
518
519double
521 Time duration,
522 WifiMode mode,
523 const WifiTxVector& txVector,
524 WifiPpduField field) const
525{
526 if (duration.IsZero())
527 {
528 return 1.0;
529 }
530 const auto rate = mode.GetDataRate(txVector.GetChannelWidth());
531 auto nbits = static_cast<uint64_t>(rate * duration.GetSeconds());
532 const auto csr =
533 m_errorRateModel->GetChunkSuccessRate(mode, txVector, snir, nbits, m_numRxAntennas, field);
534 return csr;
535}
536
537double
539 Time duration,
540 const WifiTxVector& txVector,
541 uint16_t staId) const
542{
543 if (duration.IsZero())
544 {
545 return 1.0;
546 }
547 const auto mode = txVector.GetMode(staId);
548 const auto rate = mode.GetDataRate(txVector, staId);
549 auto nbits = static_cast<uint64_t>(rate * duration.GetSeconds());
550 nbits /= txVector.GetNss(staId); // divide effective number of bits by NSS to achieve same chunk
551 // error rate as SISO for AWGN
552 double csr = m_errorRateModel->GetChunkSuccessRate(mode,
553 txVector,
554 snir,
555 nbits,
558 staId);
559 return csr;
560}
561
562double
564 MHz_u channelWidth,
565 NiChangesPerBand* nis,
566 const WifiSpectrumBandInfo& band,
567 uint16_t staId,
568 std::pair<Time, Time> window) const
569{
570 NS_LOG_FUNCTION(this << channelWidth << band << staId << window.first << window.second);
571 double psr = 1.0; /* Packet Success Rate */
572 const auto& niIt = nis->find(band)->second;
573 auto j = niIt.cbegin();
574 auto previous = j->first;
575 Watt_u muMimoPower{0.0};
576 const auto payloadMode = event->GetPpdu()->GetTxVector().GetMode(staId);
577 auto phyPayloadStart = j->first;
578 if (event->GetPpdu()->GetType() != WIFI_PPDU_TYPE_UL_MU &&
579 event->GetPpdu()->GetType() !=
580 WIFI_PPDU_TYPE_DL_MU) // j->first corresponds to the start of the MU payload
581 {
582 phyPayloadStart = j->first + WifiPhy::CalculatePhyPreambleAndHeaderDuration(
583 event->GetPpdu()->GetTxVector());
584 }
585 else
586 {
587 muMimoPower = CalculateMuMimoPowerW(event, band);
588 }
589 const auto windowStart = phyPayloadStart + window.first;
590 const auto windowEnd = phyPayloadStart + window.second;
591 NS_ABORT_IF(!m_firstPowers.contains(band));
592 auto noiseInterference = m_firstPowers.at(band);
593 auto power = event->GetRxPower(band);
594 while (++j != niIt.cend())
595 {
596 Time current = j->first;
597 NS_LOG_DEBUG("previous= " << previous << ", current=" << current);
598 NS_ASSERT(current >= previous);
599 const auto snr = CalculateSnr(power,
600 noiseInterference,
601 channelWidth,
602 event->GetPpdu()->GetTxVector().GetNss(staId));
603 // Case 1: Both previous and current point to the windowed payload
604 if (previous >= windowStart)
605 {
607 Min(windowEnd, current) - previous,
608 event->GetPpdu()->GetTxVector(),
609 staId);
610 NS_LOG_DEBUG("Both previous and current point to the windowed payload: mode="
611 << payloadMode << ", psr=" << psr);
612 }
613 // Case 2: previous is before windowed payload and current is in the windowed payload
614 else if (current >= windowStart)
615 {
617 Min(windowEnd, current) - windowStart,
618 event->GetPpdu()->GetTxVector(),
619 staId);
621 "previous is before windowed payload and current is in the windowed payload: mode="
622 << payloadMode << ", psr=" << psr);
623 }
624 noiseInterference = j->second.GetPower() - power;
625 if (IsSameMuMimoTransmission(event, j->second.GetEvent()))
626 {
627 muMimoPower += j->second.GetEvent()->GetRxPower(band);
628 NS_LOG_DEBUG("PPDU belongs to same MU-MIMO transmission: muMimoPowerW=" << muMimoPower);
629 }
630 noiseInterference -= muMimoPower;
631 previous = j->first;
632 if (previous > windowEnd)
633 {
634 NS_LOG_DEBUG("Stop: new previous=" << previous
635 << " after time window end=" << windowEnd);
636 break;
637 }
638 }
639 const auto per = 1.0 - psr;
640 return per;
641}
642
643double
645 Ptr<const Event> event,
646 NiChangesPerBand* nis,
647 MHz_u channelWidth,
648 const WifiSpectrumBandInfo& band,
649 PhyEntity::PhyHeaderSections phyHeaderSections) const
650{
651 NS_LOG_FUNCTION(this << band);
652 double psr = 1.0; /* Packet Success Rate */
653 auto niIt = nis->find(band)->second;
654 auto j = niIt.begin();
655
656 NS_ASSERT(!phyHeaderSections.empty());
657 Time stopLastSection;
658 for (const auto& section : phyHeaderSections)
659 {
660 stopLastSection = Max(stopLastSection, section.second.first.second);
661 }
662
663 auto previous = j->first;
664 NS_ABORT_IF(!m_firstPowers.contains(band));
665 auto noiseInterference = m_firstPowers.at(band);
666 const auto power = event->GetRxPower(band);
667 while (++j != niIt.end())
668 {
669 auto current = j->first;
670 NS_LOG_DEBUG("previous= " << previous << ", current=" << current);
671 NS_ASSERT(current >= previous);
672 const auto snr = CalculateSnr(power, noiseInterference, channelWidth, 1);
673 for (const auto& section : phyHeaderSections)
674 {
675 const auto start = section.second.first.first;
676 const auto stop = section.second.first.second;
677
678 if (previous <= stop || current >= start)
679 {
680 const auto duration = Min(stop, current) - Max(start, previous);
681 if (duration.IsStrictlyPositive())
682 {
683 psr *= CalculateChunkSuccessRate(snr,
684 duration,
685 section.second.second,
686 event->GetPpdu()->GetTxVector(),
687 section.first);
688 NS_LOG_DEBUG("Current NI change in "
689 << section.first << " [" << start << ", " << stop << "] for "
690 << duration.As(Time::NS) << ": mode=" << section.second.second
691 << ", psr=" << psr);
692 }
693 }
694 }
695 noiseInterference = j->second.GetPower() - power;
696 previous = j->first;
697 if (previous > stopLastSection)
698 {
699 NS_LOG_DEBUG("Stop: new previous=" << previous << " after stop of last section="
700 << stopLastSection);
701 break;
702 }
703 }
704 return psr;
705}
706
707double
709 NiChangesPerBand* nis,
710 MHz_u channelWidth,
711 const WifiSpectrumBandInfo& band,
712 WifiPpduField header) const
713{
714 NS_LOG_FUNCTION(this << band << header);
715 auto niIt = nis->find(band)->second;
716 auto phyEntity =
717 WifiPhy::GetStaticPhyEntity(event->GetPpdu()->GetTxVector().GetModulationClass());
718
720 for (const auto& section :
721 phyEntity->GetPhyHeaderSections(event->GetPpdu()->GetTxVector(), niIt.begin()->first))
722 {
723 if (section.first == header)
724 {
725 sections[header] = section.second;
726 }
727 }
728
729 double psr = 1.0;
730 if (!sections.empty())
731 {
732 psr = CalculatePhyHeaderSectionPsr(event, nis, channelWidth, band, sections);
733 }
734 return 1 - psr;
735}
736
739 MHz_u channelWidth,
740 const WifiSpectrumBandInfo& band,
741 uint16_t staId,
742 std::pair<Time, Time> relativeMpduStartStop) const
743{
744 NS_LOG_FUNCTION(this << channelWidth << band << staId << relativeMpduStartStop.first
745 << relativeMpduStartStop.second);
747 const auto noiseInterference = CalculateNoiseInterferenceW(event, ni, band);
748 const auto snr = CalculateSnr(event->GetRxPower(band),
749 noiseInterference,
750 channelWidth,
751 event->GetPpdu()->GetTxVector().GetNss(staId));
752
753 /* calculate the SNIR at the start of the MPDU (located through windowing) and accumulate
754 * all SNIR changes in the SNIR vector.
755 */
756 const auto per =
757 CalculatePayloadPer(event, channelWidth, &ni, band, staId, relativeMpduStartStop);
758
759 return PhyEntity::SnrPer(snr, per);
760}
761
762double
764 MHz_u channelWidth,
765 uint8_t nss,
766 const WifiSpectrumBandInfo& band) const
767{
769 const auto noiseInterference = CalculateNoiseInterferenceW(event, ni, band);
770 return CalculateSnr(event->GetRxPower(band), noiseInterference, channelWidth, nss);
771}
772
775 MHz_u channelWidth,
776 const WifiSpectrumBandInfo& band,
777 WifiPpduField header) const
778{
779 NS_LOG_FUNCTION(this << band << header);
781 const auto noiseInterference = CalculateNoiseInterferenceW(event, ni, band);
782 const auto snr = CalculateSnr(event->GetRxPower(band), noiseInterference, channelWidth, 1);
783
784 /* calculate the SNIR at the start of the PHY header and accumulate
785 * all SNIR changes in the SNIR vector.
786 */
787 const auto per = CalculatePhyHeaderPer(event, &ni, channelWidth, band, header);
788
789 return PhyEntity::SnrPer(snr, per);
790}
791
792InterferenceHelper::NiChanges::iterator
793InterferenceHelper::GetNextPosition(Time moment, NiChangesPerBand::iterator niIt) const
794{
795 return niIt->second.upper_bound(moment);
796}
797
798InterferenceHelper::NiChanges::iterator
799InterferenceHelper::GetPreviousPosition(Time moment, NiChangesPerBand::iterator niIt) const
800{
801 // This is safe since there is always an NiChange at time 0, before moment.
802 return std::prev(GetNextPosition(moment, niIt));
803}
804
805InterferenceHelper::NiChanges::iterator
806InterferenceHelper::AddNiChangeEvent(Time moment, NiChange change, NiChangesPerBand::iterator niIt)
807{
808 return niIt->second.insert(GetNextPosition(moment, niIt), {moment, change});
809}
810
811void
813{
814 NS_LOG_FUNCTION(this << freqRange);
815 m_rxing[freqRange] = true;
816}
817
818void
820{
821 NS_LOG_FUNCTION(this << endTime << freqRange);
822 m_rxing.at(freqRange) = false;
823 // Update m_firstPowers for frame capture
824 for (auto niIt = m_niChanges.begin(); niIt != m_niChanges.end(); ++niIt)
825 {
826 if (!IsBandInFrequencyRange(niIt->first, freqRange))
827 {
828 continue;
829 }
830 NS_ASSERT(niIt->second.size() > 1);
831 auto it = std::prev(GetPreviousPosition(endTime, niIt));
832 m_firstPowers.find(niIt->first)->second = it->second.GetPower();
833 }
834}
835
836bool
838 const FrequencyRange& freqRange) const
839{
840 return std::all_of(band.frequencies.cbegin(),
841 band.frequencies.cend(),
842 [&freqRange](const auto& freqs) {
843 return ((freqs.second > MHzToHz(freqRange.minFrequency)) &&
844 (freqs.first < MHzToHz(freqRange.maxFrequency)));
845 });
846}
847
848bool
850 Ptr<const Event> otherEvent) const
851{
852 if ((currentEvent->GetPpdu()->GetType() == WIFI_PPDU_TYPE_UL_MU) &&
853 (otherEvent->GetPpdu()->GetType() == WIFI_PPDU_TYPE_UL_MU) &&
854 (currentEvent->GetPpdu()->GetUid() == otherEvent->GetPpdu()->GetUid()))
855 {
856 const auto currentTxVector = currentEvent->GetPpdu()->GetTxVector();
857 const auto otherTxVector = otherEvent->GetPpdu()->GetTxVector();
858 NS_ASSERT(currentTxVector.GetHeMuUserInfoMap().size() == 1);
859 NS_ASSERT(otherTxVector.GetHeMuUserInfoMap().size() == 1);
860 const auto currentUserInfo = currentTxVector.GetHeMuUserInfoMap().cbegin();
861 const auto otherUserInfo = otherTxVector.GetHeMuUserInfoMap().cbegin();
862 return (currentUserInfo->second.ru == otherUserInfo->second.ru);
863 }
864 return false;
865}
866
867} // 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.
NiChanges::iterator GetNextPosition(Time moment, NiChangesPerBand::iterator niIt) const
Returns an iterator to the first NiChange that is later than moment.
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.
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...
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.
NiChanges::iterator GetPreviousPosition(Time moment, NiChangesPerBand::iterator niIt) const
Returns an iterator to the last NiChange that is before than moment.
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:49
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:38
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:110
static const Ptr< const PhyEntity > GetStaticPhyEntity(WifiModulationClass modulation)
Get the implemented PHY entity corresponding to the modulation class.
Definition wifi-phy.cc:760
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition wifi-phy.cc:1556
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:45
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
Hz_u MHzToHz(MHz_u val)
Convert from MHz to Hz.
Definition wifi-utils.h:113
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