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