A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
spectrum-wifi-phy.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 * Ghada Badawy <gbadawy@gmail.com>
8 * Sébastien Deronne <sebastien.deronne@gmail.com>
9 *
10 * Ported from yans-wifi-phy.cc by several contributors starting
11 * with Nicola Baldo and Dean Armstrong
12 */
13
14#include "spectrum-wifi-phy.h"
15
16#include "interference-helper.h"
17#include "wifi-net-device.h"
18#include "wifi-psdu.h"
21#include "wifi-utils.h"
22
23#include "ns3/boolean.h"
24#include "ns3/double.h"
25#include "ns3/he-phy.h"
26#include "ns3/log.h"
27#include "ns3/node.h"
28#include "ns3/simulator.h"
29#include "ns3/spectrum-channel.h"
30
31#include <algorithm>
32#include <numeric>
33
34#undef NS_LOG_APPEND_CONTEXT
35#define NS_LOG_APPEND_CONTEXT WIFI_PHY_NS_LOG_APPEND_CONTEXT(Ptr(this, false))
36
37namespace ns3
38{
39
40NS_LOG_COMPONENT_DEFINE("SpectrumWifiPhy");
41
42NS_OBJECT_ENSURE_REGISTERED(SpectrumWifiPhy);
43
44TypeId
46{
47 static TypeId tid =
48 TypeId("ns3::SpectrumWifiPhy")
50 .SetGroupName("Wifi")
51 .AddConstructor<SpectrumWifiPhy>()
52 .AddAttribute("DisableWifiReception",
53 "Prevent Wi-Fi frame sync from ever happening",
54 BooleanValue(false),
57 .AddAttribute(
58 "TrackSignalsFromInactiveInterfaces",
59 "Enable or disable tracking signals coming from inactive spectrum PHY interfaces",
60 BooleanValue(true),
63 .AddAttribute(
64 "TxMaskInnerBandMinimumRejection",
65 "Minimum rejection (dBr) for the inner band of the transmit spectrum mask",
66 DoubleValue(-20.0),
69 .AddAttribute(
70 "TxMaskOuterBandMinimumRejection",
71 "Minimum rejection (dBr) for the outer band of the transmit spectrum mask",
72 DoubleValue(-28.0),
75 .AddAttribute(
76 "TxMaskOuterBandMaximumRejection",
77 "Maximum rejection (dBr) for the outer band of the transmit spectrum mask",
78 DoubleValue(-40.0),
81 .AddTraceSource(
82 "SignalArrival",
83 "Trace start of all signal arrivals, including weak and foreign signals",
85 "ns3::SpectrumWifiPhy::SignalArrivalCallback");
86 return tid;
87}
88
90 : m_spectrumPhyInterfaces{},
91 m_currentSpectrumPhyInterface{nullptr},
92 m_frequenciesBeforeSwitch{},
93 m_widthsBeforeSwitch{}
94{
95 NS_LOG_FUNCTION(this);
96}
97
102
103void
113
114void
120
123{
124 NS_LOG_FUNCTION(this << spectrumPhyInterface);
125 WifiSpectrumBands bands{};
126 const auto channelWidth = spectrumPhyInterface->GetChannelWidth();
127 if (channelWidth < MHz_u{20})
128 {
129 bands.push_back(GetBandForInterface(spectrumPhyInterface, channelWidth));
130 }
131 else
132 {
133 for (MHz_u bw = channelWidth; bw >= MHz_u{20}; bw = bw / 2)
134 {
135 for (uint16_t i = 0; i < (channelWidth / bw); ++i)
136 {
137 bands.push_back(GetBandForInterface(spectrumPhyInterface, bw, i));
138 }
139 }
140 }
141 return bands;
142}
143
146 MHz_u guardBandwidth)
147{
148 HeRuBands heRuBands{};
149 const auto channelWidth = spectrumPhyInterface->GetChannelWidth();
150 for (MHz_u bw = channelWidth; bw >= MHz_u{20}; bw = bw / 2)
151 {
152 for (uint32_t i = 0; i < (channelWidth / bw); ++i)
153 {
154 for (uint32_t type = 0; type < 7; type++)
155 {
156 auto ruType = static_cast<HeRu::RuType>(type);
157 std::size_t nRus = HeRu::GetNRus(bw, ruType);
158 for (std::size_t phyIndex = 1; phyIndex <= nRus; phyIndex++)
159 {
160 HeRu::SubcarrierGroup group = HeRu::GetSubcarrierGroup(bw, ruType, phyIndex);
161 HeRu::SubcarrierRange subcarrierRange =
162 std::make_pair(group.front().first, group.back().second);
163 const auto bandIndices =
165 guardBandwidth,
166 spectrumPhyInterface->GetCenterFrequencies(),
167 spectrumPhyInterface->GetChannelWidth(),
169 subcarrierRange,
170 i);
171
173 for (const auto& indicesPerSegment : bandIndices)
174 {
175 band.indices.emplace_back(indicesPerSegment);
176 band.frequencies.emplace_back(
177 ConvertIndicesToFrequenciesForInterface(spectrumPhyInterface,
178 indicesPerSegment));
179 }
180 std::size_t index =
181 (bw == MHz_u{160} && phyIndex > nRus / 2 ? phyIndex - nRus / 2 : phyIndex);
182 const auto p20Index = GetOperatingChannel().GetPrimaryChannelIndex(MHz_u{20});
183 bool primary80IsLower80 = (p20Index < bw / MHz_u{40});
184 bool primary80 = (bw < MHz_u{160} || ruType == HeRu::RU_2x996_TONE ||
185 (primary80IsLower80 && phyIndex <= nRus / 2) ||
186 (!primary80IsLower80 && phyIndex > nRus / 2));
187 HeRu::RuSpec ru(ruType, index, primary80);
188 NS_ABORT_IF(ru.GetPhyIndex(bw, p20Index) != phyIndex);
189 heRuBands.insert({band, ru});
190 }
191 }
192 }
193 }
194 return heRuBands;
195}
196
197void
199{
200 NS_LOG_FUNCTION(this << spectrumPhyInterface);
201 auto&& bands = ComputeBands(spectrumPhyInterface);
202 WifiSpectrumBands allBands{bands};
204 {
205 const auto channelWidth = spectrumPhyInterface->GetChannelWidth();
206 auto&& heRuBands = GetHeRuBands(spectrumPhyInterface, GetGuardBandwidth(channelWidth));
207 for (const auto& bandRuPair : heRuBands)
208 {
209 allBands.push_back(bandRuPair.first);
210 }
211 spectrumPhyInterface->SetHeRuBands(std::move(heRuBands));
212 }
213
214 spectrumPhyInterface->SetBands(std::move(bands));
215
216 if (m_interference->HasBands())
217 {
218 m_interference->UpdateBands(allBands, spectrumPhyInterface->GetFrequencyRange());
219 }
220 else
221 {
222 for (const auto& band : allBands)
223 {
224 m_interference->AddBand(band);
225 }
226 }
227}
228
235
236void
238{
239 NS_LOG_FUNCTION(this << channel << freqRange);
240
241 const auto foundOverlappingChannel =
242 std::any_of(m_spectrumPhyInterfaces.cbegin(),
244 [freqRange, channel](const auto& item) {
245 const auto spectrumRange = item.first;
246 const auto noOverlap =
247 ((freqRange.minFrequency >= spectrumRange.maxFrequency) ||
248 (freqRange.maxFrequency <= spectrumRange.minFrequency));
249 return (!noOverlap);
250 });
251 NS_ABORT_MSG_IF(foundOverlappingChannel,
252 "Added a wifi spectrum channel that overlaps with another existing wifi "
253 "spectrum channel");
254
255 auto wifiSpectrumPhyInterface = CreateObject<WifiSpectrumPhyInterface>(freqRange);
256 wifiSpectrumPhyInterface->SetSpectrumWifiPhy(this);
257 wifiSpectrumPhyInterface->SetChannel(channel);
258 if (GetDevice())
259 {
260 wifiSpectrumPhyInterface->SetDevice(GetDevice());
261 }
262 m_spectrumPhyInterfaces.emplace(freqRange, wifiSpectrumPhyInterface);
263}
264
265void
267 const std::vector<MHz_u>& centerFrequencies,
268 MHz_u channelWidth)
269{
270 std::stringstream ss;
271 for (const auto& centerFrequency : centerFrequencies)
272 {
273 ss << centerFrequency << " ";
274 }
275 NS_LOG_FUNCTION(this << spectrumPhyInterface << ss.str() << channelWidth);
276
277 // We have to reset the spectrum model because we changed RF channel. Consequently,
278 // we also have to add the spectrum interface to the spectrum channel again because
279 // MultiModelSpectrumChannel keeps spectrum interfaces in a map indexed by the RX
280 // spectrum model UID (which has changed after channel switching).
281 // Both SingleModelSpectrumChannel and MultiModelSpectrumChannel ensure not to keep
282 // duplicated spectrum interfaces (the latter removes the spectrum interface and adds
283 // it again in the entry associated with the new RX spectrum model UID)
284
285 // Replace existing spectrum model with new one
286 spectrumPhyInterface->SetRxSpectrumModel(centerFrequencies,
287 channelWidth,
289 GetGuardBandwidth(channelWidth));
290
291 spectrumPhyInterface->GetChannel()->AddRx(spectrumPhyInterface);
292
293 UpdateInterferenceHelperBands(spectrumPhyInterface);
294}
295
296void
307
308void
310{
311 NS_LOG_FUNCTION(this);
312 const auto frequenciesAfter = GetOperatingChannel().GetFrequencies();
313 const auto widthsAfter = GetOperatingChannel().GetWidths();
314 if ((m_frequenciesBeforeSwitch == frequenciesAfter) && (m_widthsBeforeSwitch == widthsAfter))
315 {
316 NS_LOG_DEBUG("Same RF channel as before, do nothing");
317 if (IsInitialized())
318 {
319 SwitchMaybeToCcaBusy(nullptr);
320 }
321 return;
322 }
323
324 Ptr<WifiSpectrumPhyInterface> newSpectrumPhyInterface;
325 const auto numSegments = GetOperatingChannel().GetNSegments();
326 NS_ASSERT(numSegments == frequenciesAfter.size() && numSegments == widthsAfter.size());
327 for (std::size_t i = 0; i < numSegments; ++i)
328 {
329 auto interfaceCoveringBand =
330 GetInterfaceCoveringChannelBand(frequenciesAfter.at(i), widthsAfter.at(i));
331 NS_ABORT_MSG_IF(!interfaceCoveringBand,
332 "No spectrum channel covers frequency range ["
333 << frequenciesAfter.at(i) - (widthsAfter.at(i) / 2) << " MHz - "
334 << frequenciesAfter.at(i) + (widthsAfter.at(i) / 2) << " MHz]");
335 if (!newSpectrumPhyInterface)
336 {
337 newSpectrumPhyInterface = interfaceCoveringBand;
338 }
339 else
340 {
341 NS_ABORT_MSG_IF(interfaceCoveringBand != newSpectrumPhyInterface,
342 "All segments are not covered by the same spectrum channel");
343 }
344 }
345 const auto interfaceChanged = (newSpectrumPhyInterface != m_currentSpectrumPhyInterface);
346
347 if (interfaceChanged)
348 {
349 std::stringstream ss;
350 for (std::size_t i = 0; i < frequenciesAfter.size(); ++i)
351 {
352 ss << "(" << frequenciesAfter.at(i) << ", " << widthsAfter.at(i) << ") ";
353 }
354 NS_LOG_DEBUG("Switch to existing RF interface with frequency/width "
355 << (numSegments > 1 ? "pair" : "pairs") << " of " << ss.str());
357 {
359 }
360 }
361
362 m_currentSpectrumPhyInterface = newSpectrumPhyInterface;
363
364 auto reset = true;
365 if (m_currentSpectrumPhyInterface->GetCenterFrequencies() == frequenciesAfter)
366 {
367 // Center frequencies have not changed for that interface, hence we do not need to
368 // reset the spectrum model nor update any band stored in the interference helper
370 {
371 // If we are not tracking signals from inactive interface,
372 // this means the spectrum interface has been disconnected
373 // from the spectrum channel and has to be connected back
375 }
376 reset = false;
377 }
378
379 if (reset)
380 {
382 frequenciesAfter,
383 GetOperatingChannel().GetTotalWidth());
384 }
385
386 if (IsInitialized())
387 {
389 }
390 else
391 {
393 }
394}
395
396void
404
405void
406SpectrumWifiPhy::ConfigureInterface(const std::vector<MHz_u>& frequencies, MHz_u width)
407{
408 std::stringstream ss;
409 for (const auto& centerFrequency : frequencies)
410 {
411 ss << centerFrequency << " ";
412 }
413 NS_LOG_FUNCTION(this << ss.str() << width);
414
416 {
417 NS_LOG_DEBUG("Tracking of signals on inactive interfaces is not enabled");
418 return;
419 }
420
421 Ptr<WifiSpectrumPhyInterface> spectrumPhyInterface;
422 const auto numSegments = frequencies.size();
423 const auto segmentWidth = width / numSegments;
424 for (std::size_t i = 0; i < numSegments; ++i)
425 {
426 auto interfaceCoveringBand =
427 GetInterfaceCoveringChannelBand(frequencies.at(i), segmentWidth);
428 NS_ABORT_MSG_IF(!interfaceCoveringBand,
429 "No spectrum channel covers frequency range ["
430 << frequencies.at(i) - (segmentWidth / 2) << " MHz - "
431 << frequencies.at(i) + (segmentWidth / 2) << " MHz]");
432 if (!spectrumPhyInterface)
433 {
434 spectrumPhyInterface = interfaceCoveringBand;
435 }
436 else
437 {
438 NS_ABORT_MSG_IF(interfaceCoveringBand != spectrumPhyInterface,
439 "All segments are not covered by the same spectrum channel");
440 }
441 }
442
443 NS_ABORT_MSG_IF(spectrumPhyInterface == m_currentSpectrumPhyInterface,
444 "This method should not be called for the current interface");
445
446 if ((frequencies == spectrumPhyInterface->GetCenterFrequencies()) &&
447 (width == spectrumPhyInterface->GetChannelWidth()))
448 {
449 NS_LOG_DEBUG("Same RF channel as before on that interface, do nothing");
450 return;
451 }
452
453 ResetSpectrumModel(spectrumPhyInterface, frequencies, width);
454}
455
456bool
458{
459 return GetLatestPhyEntity()->CanStartRx(ppdu);
460}
461
462void
465{
466 NS_LOG_FUNCTION(this << rxParams << interface);
467 Time rxDuration = rxParams->duration;
468 Ptr<SpectrumValue> receivedSignalPsd = rxParams->psd;
469 if (interface)
470 {
471 NS_ASSERT_MSG(receivedSignalPsd->GetValuesN() ==
472 interface->GetRxSpectrumModel()->GetNumBands(),
473 "Incorrect spectrum conversion or multi model spectrum channel is not used!");
474 }
475 NS_LOG_DEBUG("Received signal with PSD " << *receivedSignalPsd << " and duration "
476 << rxDuration.As(Time::NS));
477 uint32_t senderNodeId = 0;
478 if (rxParams->txPhy)
479 {
480 senderNodeId = rxParams->txPhy->GetDevice()->GetNode()->GetId();
481 }
482 NS_LOG_DEBUG("Received signal from " << senderNodeId << " with unfiltered power "
483 << WToDbm(Integral(*receivedSignalPsd)) << " dBm");
484
485 // Integrate over our receive bandwidth (i.e., all that the receive
486 // spectral mask representing our filtering allows) to find the
487 // total energy apparent to the "demodulator".
488 // This is done per 20 MHz channel band.
489 const auto channelWidth = interface ? interface->GetChannelWidth() : GetChannelWidth();
490 const auto& bands =
491 interface ? interface->GetBands() : m_currentSpectrumPhyInterface->GetBands();
492 Watt_u totalRxPower{0.0};
494
495 const auto rxGainRatio = DbToRatio(GetRxGain());
496
497 std::size_t index = 0;
498 MHz_u prevBw{0};
499 for (const auto& band : bands)
500 {
501 const auto bw =
502 std::accumulate(band.frequencies.cbegin(),
503 band.frequencies.cend(),
504 MHz_u{0},
505 [](MHz_u sum, const auto& startStopFreqs) {
506 return sum + HzToMHz(startStopFreqs.second - startStopFreqs.first);
507 });
508 NS_ASSERT(bw <= channelWidth);
509 index = ((bw != prevBw) ? 0 : (index + 1));
510 auto rxPowerPerBand =
511 WifiSpectrumValueHelper::GetBandPowerW(receivedSignalPsd, band.indices);
512 NS_LOG_DEBUG("Signal power received (watts) before antenna gain for "
513 << bw << " MHz channel band " << index << ": " << band);
514 rxPowerPerBand *= rxGainRatio;
515 rxPowers.insert({band, rxPowerPerBand});
516 NS_LOG_DEBUG("Signal power received after antenna gain for "
517 << bw << " MHz channel band " << index << ": " << rxPowerPerBand << " W"
518 << (rxPowerPerBand > Watt_u{0.0}
519 ? " (" + std::to_string(WToDbm(rxPowerPerBand)) + " dBm)"
520 : ""));
521 if (bw <= MHz_u{20})
522 {
523 totalRxPower += rxPowerPerBand;
524 }
525 prevBw = bw;
526 }
527
529 {
530 const auto& heRuBands =
531 interface ? interface->GetHeRuBands() : m_currentSpectrumPhyInterface->GetHeRuBands();
532 NS_ASSERT(!heRuBands.empty());
533 for (const auto& [band, ru] : heRuBands)
534 {
535 auto rxPowerPerBand =
536 WifiSpectrumValueHelper::GetBandPowerW(receivedSignalPsd, band.indices);
537 rxPowerPerBand *= rxGainRatio;
538 rxPowers.insert({band, rxPowerPerBand});
539 }
540 }
541
542 NS_ASSERT_MSG(totalRxPower >= Watt_u{0.0}, "Negative RX power");
543 NS_LOG_DEBUG("Total signal power received after antenna gain: "
544 << totalRxPower << " W"
545 << (totalRxPower > Watt_u{0.0}
546 ? " (" + std::to_string(WToDbm(totalRxPower)) + " dBm)"
547 : ""));
548
551
552 // Log the signal arrival to the trace source
553 if (totalRxPower > Watt_u{0.0})
554 {
555 m_signalCb(rxParams, senderNodeId, WToDbm(totalRxPower), rxDuration);
556 }
557
558 if (m_trackSignalsInactiveInterfaces && interface &&
559 (interface != m_currentSpectrumPhyInterface))
560 {
561 NS_LOG_INFO("Received Wi-Fi signal from a non-active PHY interface "
562 << interface->GetFrequencyRange());
563 m_interference->AddForeignSignal(rxDuration, rxPowers, interface->GetFrequencyRange());
564 return;
565 }
566
567 if (!wifiRxParams)
568 {
569 NS_LOG_INFO("Received non Wi-Fi signal");
570 m_interference->AddForeignSignal(rxDuration,
571 rxPowers,
572 interface ? interface->GetFrequencyRange()
574 SwitchMaybeToCcaBusy(nullptr);
575 return;
576 }
577
578 if (wifiRxParams && m_disableWifiReception)
579 {
580 NS_LOG_INFO("Received Wi-Fi signal but blocked from syncing");
581 NS_ASSERT(interface);
582 m_interference->AddForeignSignal(rxDuration, rxPowers, interface->GetFrequencyRange());
583 SwitchMaybeToCcaBusy(nullptr);
584 return;
585 }
586
587 // Do no further processing if signal is too weak
588 // Current implementation assumes constant RX power over the PPDU duration
589 // Compare received TX power per MHz to normalized RX sensitivity
590 const auto ppdu = GetRxPpduFromTxPpdu(wifiRxParams->ppdu);
591 if (totalRxPower < DbmToW(GetRxSensitivity()) * (ppdu->GetTxChannelWidth() / MHz_u{20}))
592 {
593 NS_LOG_INFO("Received signal too weak to process: "
594 << totalRxPower << " W"
595 << (totalRxPower > Watt_u{0.0}
596 ? " (" + std::to_string(WToDbm(totalRxPower)) + " dBm)"
597 : ""));
598 m_interference->Add(ppdu, rxDuration, rxPowers, GetCurrentFrequencyRange());
599 SwitchMaybeToCcaBusy(nullptr);
600 return;
601 }
602
603 if (wifiRxParams->txPhy)
604 {
605 if (!CanStartRx(ppdu))
606 {
607 NS_LOG_INFO("Cannot start reception of the PPDU, consider it as interference");
608 m_interference->Add(ppdu, rxDuration, rxPowers, GetCurrentFrequencyRange());
610 return;
611 }
612 }
613
614 NS_LOG_INFO("Received Wi-Fi signal");
615 StartReceivePreamble(ppdu, rxPowers, rxDuration);
616}
617
620{
621 return GetPhyEntityForPpdu(ppdu)->GetRxPpduFromTxPpdu(ppdu);
622}
623
626{
627 return m_antenna;
628}
629
630void
632{
633 NS_LOG_FUNCTION(this << a);
634 m_antenna = a;
635}
636
637void
639{
640 NS_LOG_FUNCTION(this << device);
641 WifiPhy::SetDevice(device);
642 for (auto& spectrumPhyInterface : m_spectrumPhyInterfaces)
643 {
644 spectrumPhyInterface.second->SetDevice(device);
645 }
646}
647
648void
650{
651 NS_LOG_FUNCTION(this << ppdu);
652 m_signalTransmissionCb(ppdu, ppdu->GetTxVector());
653 GetPhyEntity(ppdu->GetModulation())->StartTx(ppdu);
654}
655
656void
663
664MHz_u
666{
667 MHz_u guardBandwidth{0};
668 if (currentChannelWidth == MHz_u{22})
669 {
670 // handle case of DSSS transmission
671 guardBandwidth = MHz_u{10};
672 }
673 else
674 {
675 // In order to properly model out of band transmissions for OFDM, the guard
676 // band has been configured so as to expand the modeled spectrum up to the
677 // outermost referenced point in "Transmit spectrum mask" sections' PSDs of
678 // each PHY specification of 802.11-2016 standard. It thus ultimately corresponds
679 // to the currently considered channel bandwidth (which can be different from
680 // supported channel width).
681 guardBandwidth = currentChannelWidth;
682 }
683 return guardBandwidth;
684}
685
687SpectrumWifiPhy::GetNumBandsBetweenSegments(const std::vector<MHz_u>& centerFrequencies,
688 MHz_u totalWidth,
689 Hz_u subcarrierSpacing)
690{
691 const auto numSegments = centerFrequencies.size();
692 NS_ABORT_MSG_IF(numSegments > 2, "Only 2 non-contiguous frequency segments are supported");
693 if (numSegments < 2)
694 {
695 return 0;
696 }
697 const auto lowFrequency = *centerFrequencies.cbegin();
698 const auto highFrequency = *centerFrequencies.crbegin();
699 NS_ASSERT(lowFrequency != highFrequency);
700 // all segments have the same width
701 const auto segmentsWidth = totalWidth / numSegments;
702 const auto widthBetweenSegments = highFrequency - lowFrequency - segmentsWidth;
703 return MHzToHz(widthBetweenSegments) / subcarrierSpacing;
704}
705
708 MHz_u bandWidth,
709 uint8_t bandIndex /* = 0 */)
710{
711 const auto channelWidth = spectrumPhyInterface->GetChannelWidth();
712 NS_ASSERT_MSG(bandWidth <= channelWidth,
713 "Bandwidth (" << bandWidth << ") cannot exceed total operating channel width ("
714 << channelWidth << ")");
715 const auto subcarrierSpacing = GetSubcarrierSpacing();
716 WifiSpectrumBandInfo bandInfo;
717 std::size_t numSegments = 1;
718 if (const auto segmentWidth =
719 (channelWidth / spectrumPhyInterface->GetCenterFrequencies().size());
720 bandWidth > segmentWidth)
721 {
722 NS_ASSERT(bandIndex == 0);
723 numSegments = spectrumPhyInterface->GetCenterFrequencies().size();
724 bandWidth /= spectrumPhyInterface->GetCenterFrequencies().size();
725 }
726 const auto numBandsInBand = static_cast<size_t>(MHzToHz(bandWidth) / subcarrierSpacing);
727 auto numBandsInChannel = static_cast<size_t>(MHzToHz(channelWidth) / subcarrierSpacing);
728 const auto numBands = channelWidth / bandWidth;
729 if (numBandsInBand % 2 == 0)
730 {
731 numBandsInChannel += 1; // symmetry around center frequency
732 }
733 auto rxSpectrumModel = spectrumPhyInterface->GetRxSpectrumModel();
734 size_t totalNumBands = rxSpectrumModel->GetNumBands();
735 NS_ASSERT_MSG((numBandsInChannel % 2 == 1) && (totalNumBands % 2 == 1),
736 "Should have odd number of bands");
737 for (std::size_t segmentIndex = 0; segmentIndex < numSegments; ++segmentIndex)
738 {
739 NS_ASSERT_MSG(bandIndex < numBands, "Band index is out of bound");
740 NS_ASSERT(totalNumBands >= numBandsInChannel);
741 const auto numBandsBetweenSegments =
742 GetNumBandsBetweenSegments(spectrumPhyInterface->GetCenterFrequencies(),
743 channelWidth,
745 auto startIndex = ((totalNumBands - numBandsInChannel - numBandsBetweenSegments) / 2) +
746 (bandIndex * numBandsInBand);
747 if (bandIndex >= (numBands / 2))
748 {
749 startIndex += numBandsBetweenSegments;
750 }
751 auto stopIndex = startIndex + numBandsInBand - 1;
752 auto frequencies =
753 ConvertIndicesToFrequenciesForInterface(spectrumPhyInterface, {startIndex, stopIndex});
754 auto freqRange = spectrumPhyInterface->GetFrequencyRange();
755 NS_ASSERT(frequencies.first >= MHzToHz(freqRange.minFrequency));
756 NS_ASSERT(frequencies.second <= MHzToHz(freqRange.maxFrequency));
757 NS_ASSERT((frequencies.second - frequencies.first) == MHzToHz(bandWidth));
758 if (startIndex >= totalNumBands / 2)
759 {
760 // step past DC
761 startIndex += 1;
762 }
763 bandInfo.indices.emplace_back(startIndex, stopIndex);
764 bandInfo.frequencies.emplace_back(frequencies);
765 ++bandIndex;
766 }
767 return bandInfo;
768}
769
771SpectrumWifiPhy::GetBand(MHz_u bandWidth, uint8_t bandIndex /* = 0 */)
772{
774 return GetBandForInterface(m_currentSpectrumPhyInterface, bandWidth, bandIndex);
775}
776
783
786 Ptr<WifiSpectrumPhyInterface> spectrumPhyInterface,
787 const WifiSpectrumBandIndices& indices) const
788{
789 NS_ABORT_IF(!spectrumPhyInterface);
790 auto rxSpectrumModel = spectrumPhyInterface->GetRxSpectrumModel();
791 auto startGuardBand = rxSpectrumModel->Begin();
792 auto startChannel = std::next(startGuardBand, indices.first);
793 auto endChannel = std::next(startGuardBand, indices.second + 1);
794 return {Hz_u{startChannel->fc}, Hz_u{endChannel->fc}};
795}
796
797std::tuple<dBr_u, dBr_u, dBr_u>
804
811
812const std::map<FrequencyRange, Ptr<WifiSpectrumPhyInterface>>&
817
820{
821 const auto lowFreq = frequency - (width / 2);
822 const auto highFreq = frequency + (width / 2);
823 const auto it = std::find_if(m_spectrumPhyInterfaces.cbegin(),
825 [lowFreq, highFreq](const auto& item) {
826 return ((lowFreq >= item.first.minFrequency) &&
827 (highFreq <= item.first.maxFrequency));
828 });
829 if (it == std::end(m_spectrumPhyInterfaces))
830 {
831 return nullptr;
832 }
833 return it->second;
834}
835
841
842void
847
848} // namespace ns3
AttributeValue implementation for Boolean.
Definition boolean.h:26
Callback template class.
Definition callback.h:422
void Nullify()
Discard the implementation, set it to null.
Definition callback.h:561
bool IsNull() const
Check for null implementation.
Definition callback.h:555
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
static std::vector< WifiSpectrumBandIndices > ConvertHeRuSubcarriers(MHz_u bandWidth, MHz_u guardBandwidth, const std::vector< MHz_u > &centerFrequencies, MHz_u totalWidth, Hz_u subcarrierSpacing, HeRu::SubcarrierRange subcarrierRange, uint8_t bandIndex=0)
Definition he-phy.cc:1852
RU Specification.
Definition he-ru.h:57
std::size_t GetPhyIndex(MHz_u bw, uint8_t p20Index) const
Get the RU PHY index.
Definition he-ru.cc:468
static SubcarrierGroup GetSubcarrierGroup(MHz_u bw, RuType ruType, std::size_t phyIndex)
Get the subcarrier group of the RU having the given PHY index among all the RUs of the given type (nu...
Definition he-ru.cc:580
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
Definition he-ru.h:46
std::pair< int16_t, int16_t > SubcarrierRange
(lowest index, highest index) pair defining a subcarrier range
Definition he-ru.h:43
static std::size_t GetNRus(MHz_u bw, RuType ruType)
Get the number of distinct RUs of the given type (number of tones) available in a HE PPDU of the give...
Definition he-ru.cc:484
RuType
The different HE Resource Unit (RU) types.
Definition he-ru.h:32
@ RU_2x996_TONE
Definition he-ru.h:39
bool IsInitialized() const
Check if the object has been initialized.
Definition object.cc:240
Smart pointer class similar to boost::intrusive_ptr.
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:594
802.11 PHY layer model
std::vector< MHz_u > m_frequenciesBeforeSwitch
center frequency before channel switch
WifiSpectrumBandInfo GetBand(MHz_u bandWidth, uint8_t bandIndex=0) override
Get the info of a given band.
void SetDevice(const Ptr< WifiNetDevice > device) override
Sets the device this PHY is associated with.
void Transmit(Ptr< WifiSpectrumSignalParameters > txParams)
This function is sending the signal to the Spectrum channel after finishing the configuration of the ...
dBr_u m_txMaskInnerBandMinimumRejection
The minimum rejection for the inner band of the transmit spectrum mask.
std::vector< MHz_u > m_widthsBeforeSwitch
channel width before channel switch
WifiSpectrumBands ComputeBands(Ptr< WifiSpectrumPhyInterface > spectrumPhyInterface)
This function computes the bands that belong to a given spectrum PHY interface.
void StartRx(Ptr< SpectrumSignalParameters > rxParams, Ptr< const WifiSpectrumPhyInterface > interface)
Input method for delivering a signal from the spectrum channel and low-level PHY interface to this Sp...
void DoInitialize() override
Initialize() implementation.
void FinalizeChannelSwitch() override
Method that can be overridden by subclasses to perform operations after the channel is actually switc...
dBr_u m_txMaskOuterBandMinimumRejection
The minimum rejection for the outer band of the transmit spectrum mask.
std::map< FrequencyRange, Ptr< WifiSpectrumPhyInterface > > m_spectrumPhyInterfaces
Spectrum PHY interfaces.
WifiSpectrumBandFrequencies ConvertIndicesToFrequenciesForInterface(Ptr< WifiSpectrumPhyInterface > spectrumPhyInterface, const WifiSpectrumBandIndices &indices) const
This is a helper function to convert start and stop indices to start and stop frequencies.
HeRuBands GetHeRuBands(Ptr< WifiSpectrumPhyInterface > spectrumPhyInterface, MHz_u guardBandwidth)
This function computes the RU bands that belong to a given spectrum PHY interface.
Ptr< AntennaModel > m_antenna
antenna model
FrequencyRange GetCurrentFrequencyRange() const override
Get the frequency range of the current RF interface.
Ptr< const WifiPpdu > GetRxPpduFromTxPpdu(Ptr< const WifiPpdu > ppdu)
Determine the WifiPpdu to be used by the RX PHY based on the WifiPpdu sent by the TX PHY.
MHz_u GetGuardBandwidth(MHz_u currentChannelWidth) const override
Ptr< WifiSpectrumPhyInterface > GetInterfaceCoveringChannelBand(MHz_u frequency, MHz_u width) const
Get the spectrum PHY interface that covers a band portion of the RF channel.
Ptr< AntennaModel > GetAntenna() const
Get the antenna model used for reception.
std::tuple< dBr_u, dBr_u, dBr_u > GetTxMaskRejectionParams() const override
Ptr< Channel > GetChannel() const override
Return the Channel this WifiPhy is connected to.
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
void SetChannelSwitchedCallback(Callback< void > callback)
Ptr< WifiSpectrumPhyInterface > m_currentSpectrumPhyInterface
The current Spectrum PHY interface (held for performance reasons)
Ptr< WifiSpectrumPhyInterface > GetCurrentInterface() const
Get the currently active spectrum PHY interface.
bool m_trackSignalsInactiveInterfaces
flag whether signals coming from inactive spectrum PHY interfaces are tracked
void DoDispose() override
Destructor implementation.
const std::map< FrequencyRange, Ptr< WifiSpectrumPhyInterface > > & GetSpectrumPhyInterfaces() const
Get the map of interfaces attached to this spectrum PHY.
static TypeId GetTypeId()
Get the type ID.
TracedCallback< Ptr< const SpectrumSignalParameters >, uint32_t, double, Time > m_signalCb
Signal callback.
Callback< void > m_channelSwitchedCallback
Callback when channel switched.
void SetAntenna(const Ptr< AntennaModel > antenna)
void ResetSpectrumModel(Ptr< WifiSpectrumPhyInterface > spectrumPhyInterface, const std::vector< MHz_u > &centerFrequencies, MHz_u channelWidth)
Perform run-time spectrum model change.
void ConfigureInterface(const std::vector< MHz_u > &frequencies, MHz_u width)
Configure a non-active spectrum PHY interface to operate on a given frequency (or several frequencies...
bool m_disableWifiReception
forces this PHY to fail to sync on any signal
bool CanStartRx(Ptr< const WifiPpdu > ppdu) const
Determine whether the PHY shall issue a PHY-RXSTART.indication primitive in response to a given PPDU.
void UpdateInterferenceHelperBands(Ptr< WifiSpectrumPhyInterface > spectrumPhyInterface)
This function is called to update the bands handled by the InterferenceHelper.
void StartTx(Ptr< const WifiPpdu > ppdu) override
dBr_u m_txMaskOuterBandMaximumRejection
The maximum rejection for the outer band of the transmit spectrum mask.
void NotifyChannelSwitched()
Notify the spectrum channel has switched.
void DoChannelSwitch() override
Actually switch channel based on the stored channel settings.
static uint32_t GetNumBandsBetweenSegments(const std::vector< MHz_u > &centerFrequencies, MHz_u totalWidth, Hz_u subcarrierSpacing)
Determine the number of bands between the two segments if the operating channel is made of non-contig...
WifiSpectrumBandFrequencies ConvertIndicesToFrequencies(const WifiSpectrumBandIndices &indices) const override
This is a helper function to convert start and stop indices to start and stop frequencies.
WifiSpectrumBandInfo GetBandForInterface(Ptr< WifiSpectrumPhyInterface > spectrumPhyInterface, MHz_u bandWidth, uint8_t bandIndex=0)
Get the info of a given band that belongs to a given spectrum PHY interface.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:404
@ NS
nanosecond
Definition nstime.h:108
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
802.11 PHY layer model
Definition wifi-phy.h:55
dBm_u GetRxSensitivity() const
Return the receive sensitivity threshold.
Definition wifi-phy.cc:520
Hz_u GetSubcarrierSpacing() const
Definition wifi-phy.cc:2369
TracedCallback< Ptr< const WifiPpdu >, const WifiTxVector & > m_signalTransmissionCb
Signal Transmission callback.
Definition wifi-phy.h:1368
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition wifi-phy.cc:760
virtual void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition wifi-phy.cc:641
void StartReceivePreamble(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW, Time rxDuration)
Start receiving the PHY preamble of a PPDU (i.e.
Definition wifi-phy.cc:1978
MHz_u GetChannelWidth() const
Definition wifi-phy.cc:1099
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition wifi-phy.cc:647
void DoDispose() override
Destructor implementation.
Definition wifi-phy.cc:436
dB_u GetRxGain() const
Return the reception gain.
Definition wifi-phy.cc:622
virtual void DoChannelSwitch()
Actually switch channel based on the stored channel settings.
Definition wifi-phy.cc:1234
void SwitchMaybeToCcaBusy(const Ptr< const WifiPpdu > ppdu=nullptr)
Check if PHY state should move to CCA busy state based on current state of interference tracker.
Definition wifi-phy.cc:2215
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition wifi-phy.h:1327
void DoInitialize() override
Initialize() implementation.
Definition wifi-phy.cc:411
WifiStandard GetStandard() const
Get the configured Wi-Fi standard.
Definition wifi-phy.cc:1075
Ptr< PhyEntity > GetPhyEntityForPpdu(const Ptr< const WifiPpdu > ppdu) const
Get the supported PHY entity to use for a received PPDU.
Definition wifi-phy.cc:781
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition wifi-phy.cc:1081
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition wifi-phy.cc:775
bool IsSet() const
Return true if a valid channel has been set, false otherwise.
std::size_t GetNSegments() const
Get the number of frequency segments in the operating channel.
uint8_t GetPrimaryChannelIndex(MHz_u primaryChannelWidth) const
If the operating channel width is a multiple of 20 MHz, return the index of the primary channel of th...
std::vector< MHz_u > GetFrequencies() const
Return the center frequency per segment.
std::vector< MHz_u > GetWidths() const
Return the channel width per segment.
static Watt_u GetBandPowerW(Ptr< SpectrumValue > psd, const std::vector< WifiSpectrumBandIndices > &segments)
Calculate the power of the specified band composed of uniformly-sized sub-bands.
#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
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeChecker > MakeDoubleChecker()
Definition double.h:82
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition double.h:32
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#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_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
@ WIFI_STANDARD_80211ax
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::map< WifiSpectrumBandInfo, HeRu::RuSpec > HeRuBands
Map a spectrum band associated with an RU to the RU specification.
double Integral(const SpectrumValue &arg)
dBm_u WToDbm(Watt_u val)
Convert from Watts to dBm.
Definition wifi-utils.cc:37
std::vector< WifiSpectrumBandInfo > WifiSpectrumBands
vector of spectrum bands
double MHz_u
MHz weak type.
Definition wifi-units.h:31
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
std::pair< Hz_u, Hz_u > WifiSpectrumBandFrequencies
typedef for a pair of start and stop frequencies to represent a band
std::map< WifiSpectrumBandInfo, Watt_u > RxPowerWattPerChannelBand
A map of the received power for each band.
Definition phy-entity.h:45
double DbToRatio(dB_u val)
Convert from dB to ratio.
Definition wifi-utils.cc:25
Watt_u DbmToW(dBm_u val)
Convert from dBm to Watts.
Definition wifi-utils.cc:31
Hz_u MHzToHz(MHz_u val)
Convert from MHz to Hz.
Definition wifi-utils.h:109
std::pair< uint32_t, uint32_t > WifiSpectrumBandIndices
typedef for a pair of start and stop sub-band indices
Struct defining a frequency range between minFrequency and maxFrequency.
WifiSpectrumBandInfo structure containing info about a spectrum band.
std::vector< WifiSpectrumBandFrequencies > frequencies
the start and stop frequencies for each segment of the band
std::vector< WifiSpectrumBandIndices > indices
the start and stop indices for each segment of the band