A Discrete-Event Network Simulator
API
spectrum-wifi-phy.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  * Ghada Badawy <gbadawy@gmail.com>
19  * Sébastien Deronne <sebastien.deronne@gmail.com>
20  *
21  * Ported from yans-wifi-phy.cc by several contributors starting
22  * with Nicola Baldo and Dean Armstrong
23  */
24 
25 #include "spectrum-wifi-phy.h"
26 
27 #include "interference-helper.h"
28 #include "wifi-net-device.h"
29 #include "wifi-psdu.h"
32 #include "wifi-utils.h"
33 
34 #include "ns3/boolean.h"
35 #include "ns3/double.h"
36 #include "ns3/he-phy.h"
37 #include "ns3/log.h"
38 #include "ns3/node.h"
39 #include "ns3/simulator.h"
40 #include "ns3/spectrum-channel.h"
41 
42 #include <algorithm>
43 
44 namespace ns3
45 {
46 
47 NS_LOG_COMPONENT_DEFINE("SpectrumWifiPhy");
48 
49 NS_OBJECT_ENSURE_REGISTERED(SpectrumWifiPhy);
50 
51 TypeId
53 {
54  static TypeId tid =
55  TypeId("ns3::SpectrumWifiPhy")
56  .SetParent<WifiPhy>()
57  .SetGroupName("Wifi")
58  .AddConstructor<SpectrumWifiPhy>()
59  .AddAttribute("DisableWifiReception",
60  "Prevent Wi-Fi frame sync from ever happening",
61  BooleanValue(false),
64  .AddAttribute(
65  "TrackSignalsFromInactiveInterfaces",
66  "Enable or disable tracking signals coming from inactive spectrum PHY interfaces",
67  BooleanValue(true),
70  .AddAttribute(
71  "TxMaskInnerBandMinimumRejection",
72  "Minimum rejection (dBr) for the inner band of the transmit spectrum mask",
73  DoubleValue(-20.0),
75  MakeDoubleChecker<double>())
76  .AddAttribute(
77  "TxMaskOuterBandMinimumRejection",
78  "Minimum rejection (dBr) for the outer band of the transmit spectrum mask",
79  DoubleValue(-28.0),
81  MakeDoubleChecker<double>())
82  .AddAttribute(
83  "TxMaskOuterBandMaximumRejection",
84  "Maximum rejection (dBr) for the outer band of the transmit spectrum mask",
85  DoubleValue(-40.0),
87  MakeDoubleChecker<double>())
88  .AddTraceSource("SignalArrival",
89  "Signal arrival",
91  "ns3::SpectrumWifiPhy::SignalArrivalCallback");
92  return tid;
93 }
94 
96  : m_spectrumPhyInterfaces{},
97  m_currentSpectrumPhyInterface{nullptr}
98 {
99  NS_LOG_FUNCTION(this);
100 }
101 
103 {
104  NS_LOG_FUNCTION(this);
105 }
106 
107 void
109 {
110  NS_LOG_FUNCTION(this);
111  m_spectrumPhyInterfaces.clear();
113  m_antenna = nullptr;
116 }
117 
118 void
120 {
121  NS_LOG_FUNCTION(this);
123 }
124 
127 {
128  NS_LOG_FUNCTION(this << spectrumPhyInterface);
129  WifiSpectrumBands bands{};
130  const auto channelWidth = spectrumPhyInterface->GetChannelWidth();
131  if (channelWidth < 20)
132  {
133  bands.push_back(GetBandForInterface(spectrumPhyInterface, channelWidth));
134  }
135  else
136  {
137  for (uint16_t bw = 160; bw >= 20; bw = bw / 2)
138  {
139  for (uint32_t i = 0; i < (channelWidth / bw); ++i)
140  {
141  bands.push_back(GetBandForInterface(spectrumPhyInterface, bw, i));
142  }
143  }
144  }
145  return bands;
146 }
147 
148 HeRuBands
150  uint16_t guardBandwidth)
151 {
152  HeRuBands heRuBands{};
153  const auto channelWidth = spectrumPhyInterface->GetChannelWidth();
154  for (uint16_t bw = 160; bw >= 20; bw = bw / 2)
155  {
156  for (uint32_t i = 0; i < (channelWidth / bw); ++i)
157  {
158  for (uint32_t type = 0; type < 7; type++)
159  {
160  auto ruType = static_cast<HeRu::RuType>(type);
161  std::size_t nRus = HeRu::GetNRus(bw, ruType);
162  for (std::size_t phyIndex = 1; phyIndex <= nRus; phyIndex++)
163  {
164  HeRu::SubcarrierGroup group = HeRu::GetSubcarrierGroup(bw, ruType, phyIndex);
165  HeRu::SubcarrierRange subcarrierRange =
166  std::make_pair(group.front().first, group.back().second);
167  const auto bandIndices = HePhy::ConvertHeRuSubcarriers(bw,
168  guardBandwidth,
170  subcarrierRange,
171  i);
172  const auto bandFrequencies =
173  ConvertIndicesToFrequenciesForInterface(spectrumPhyInterface, bandIndices);
174  WifiSpectrumBandInfo band = {bandIndices, bandFrequencies};
175  std::size_t index =
176  (bw == 160 && phyIndex > nRus / 2 ? phyIndex - nRus / 2 : phyIndex);
177  const auto p20Index = GetOperatingChannel().GetPrimaryChannelIndex(20);
178  bool primary80IsLower80 = (p20Index < bw / 40);
179  bool primary80 = (bw < 160 || ruType == HeRu::RU_2x996_TONE ||
180  (primary80IsLower80 && phyIndex <= nRus / 2) ||
181  (!primary80IsLower80 && phyIndex > nRus / 2));
182  HeRu::RuSpec ru(ruType, index, primary80);
183  NS_ABORT_IF(ru.GetPhyIndex(bw, p20Index) != phyIndex);
184  heRuBands.insert({band, ru});
185  }
186  }
187  }
188  }
189  return heRuBands;
190 }
191 
192 void
194 {
195  NS_LOG_FUNCTION(this << spectrumPhyInterface);
196  auto&& bands = ComputeBands(spectrumPhyInterface);
197  WifiSpectrumBands allBands{bands};
199  {
200  const auto channelWidth = spectrumPhyInterface->GetChannelWidth();
201  auto&& heRuBands = GetHeRuBands(spectrumPhyInterface, GetGuardBandwidth(channelWidth));
202  for (const auto& bandRuPair : heRuBands)
203  {
204  allBands.push_back(bandRuPair.first);
205  }
206  spectrumPhyInterface->SetHeRuBands(std::move(heRuBands));
207  }
208 
209  spectrumPhyInterface->SetBands(std::move(bands));
210 
211  if (m_interference->HasBands())
212  {
213  m_interference->UpdateBands(allBands, spectrumPhyInterface->GetFrequencyRange());
214  }
215  else
216  {
217  for (const auto& band : allBands)
218  {
219  m_interference->AddBand(band);
220  }
221  }
222 }
223 
226 {
228  return m_currentSpectrumPhyInterface->GetChannel();
229 }
230 
231 void
233 {
234  NS_LOG_FUNCTION(this << channel << freqRange);
235 
236  const auto foundOverlappingChannel =
237  std::any_of(m_spectrumPhyInterfaces.cbegin(),
239  [freqRange, channel](const auto& item) {
240  const auto spectrumRange = item.first;
241  const auto noOverlap =
242  ((freqRange.minFrequency >= spectrumRange.maxFrequency) ||
243  (freqRange.maxFrequency <= spectrumRange.minFrequency));
244  return (!noOverlap);
245  });
246  NS_ABORT_MSG_IF(foundOverlappingChannel,
247  "Added a wifi spectrum channel that overlaps with another existing wifi "
248  "spectrum channel");
249 
250  auto wifiSpectrumPhyInterface = CreateObject<WifiSpectrumPhyInterface>(freqRange);
251  wifiSpectrumPhyInterface->SetSpectrumWifiPhy(this);
252  wifiSpectrumPhyInterface->SetChannel(channel);
253  if (GetDevice())
254  {
255  wifiSpectrumPhyInterface->SetDevice(GetDevice());
256  }
257  m_spectrumPhyInterfaces.emplace(freqRange, wifiSpectrumPhyInterface);
258 }
259 
260 void
262  uint16_t centerFrequency,
263  uint16_t channelWidth)
264 {
265  NS_LOG_FUNCTION(this << spectrumPhyInterface << centerFrequency << channelWidth);
266 
267  // We have to reset the spectrum model because we changed RF channel. Consequently,
268  // we also have to add the spectrum interface to the spectrum channel again because
269  // MultiModelSpectrumChannel keeps spectrum interfaces in a map indexed by the RX
270  // spectrum model UID (which has changed after channel switching).
271  // Both SingleModelSpectrumChannel and MultiModelSpectrumChannel ensure not to keep
272  // duplicated spectrum interfaces (the latter removes the spectrum interface and adds
273  // it again in the entry associated with the new RX spectrum model UID)
274 
275  // Replace existing spectrum model with new one
276  spectrumPhyInterface->SetRxSpectrumModel(centerFrequency,
277  channelWidth,
279  GetGuardBandwidth(channelWidth));
280 
281  spectrumPhyInterface->GetChannel()->AddRx(spectrumPhyInterface);
282 
283  UpdateInterferenceHelperBands(spectrumPhyInterface);
284 }
285 
286 void
288 {
289  NS_LOG_FUNCTION(this);
290  const auto frequencyBefore = GetOperatingChannel().IsSet() ? GetFrequency() : 0;
291  const auto widthBefore = GetOperatingChannel().IsSet() ? GetChannelWidth() : 0;
293  const auto frequencyAfter = GetFrequency();
294  const auto widthAfter = GetChannelWidth();
295  if ((frequencyBefore == frequencyAfter) && (widthBefore == widthAfter))
296  {
297  NS_LOG_DEBUG("Same RF channel as before, do nothing");
298  if (IsInitialized())
299  {
300  SwitchMaybeToCcaBusy(nullptr);
301  }
302  return;
303  }
304 
305  auto newSpectrumPhyInterface = GetInterfaceCoveringChannelBand(frequencyAfter, widthAfter);
306  const auto interfaceChanged = (newSpectrumPhyInterface != m_currentSpectrumPhyInterface);
307 
308  NS_ABORT_MSG_IF(!newSpectrumPhyInterface,
309  "No spectrum channel covers frequency range ["
310  << frequencyAfter - (widthAfter / 2) << " MHz - "
311  << frequencyAfter + (widthAfter / 2) << " MHz]");
312 
313  if (interfaceChanged)
314  {
315  NS_LOG_DEBUG("Switch to existing RF interface with frequency/width pair of ("
316  << frequencyAfter << ", " << widthAfter << ")");
318  {
320  }
321  }
322 
323  m_currentSpectrumPhyInterface = newSpectrumPhyInterface;
324 
325  auto reset = true;
326  if (m_currentSpectrumPhyInterface->GetCenterFrequency() == frequencyAfter)
327  {
328  // Center frequency has not changed for that interface, hence we do not need to
329  // reset the spectrum model nor update any band stored in the interference helper
331  {
332  // If we are not tracking signals from inactive interface,
333  // this means the spectrum interface has been disconnected
334  // from the spectrum channel and has to be connected back
336  }
337  reset = false;
338  }
339 
340  if (reset)
341  {
342  ResetSpectrumModel(m_currentSpectrumPhyInterface, frequencyAfter, widthAfter);
343  }
344 
345  if (IsInitialized())
346  {
347  SwitchMaybeToCcaBusy(nullptr);
348  }
349 
351 }
352 
353 void
355 {
357  {
359  }
360 }
361 
362 void
363 SpectrumWifiPhy::ConfigureInterface(uint16_t frequency, uint16_t width)
364 {
365  NS_LOG_FUNCTION(this << frequency << width);
366 
368  {
369  NS_LOG_DEBUG("Tracking of signals on inactive interfaces is not enabled");
370  return;
371  }
372 
373  auto spectrumPhyInterface = GetInterfaceCoveringChannelBand(frequency, width);
374 
375  NS_ABORT_MSG_IF(!spectrumPhyInterface,
376  "No spectrum channel covers frequency range ["
377  << frequency - (width / 2) << " MHz - " << frequency + (width / 2)
378  << " MHz]");
379 
380  NS_ABORT_MSG_IF(spectrumPhyInterface == m_currentSpectrumPhyInterface,
381  "This method should not be called for the current interface");
382 
383  if ((frequency == spectrumPhyInterface->GetCenterFrequency()) &&
384  (width == spectrumPhyInterface->GetChannelWidth()))
385  {
386  NS_LOG_DEBUG("Same RF channel as before on that interface, do nothing");
387  return;
388  }
389 
390  ResetSpectrumModel(spectrumPhyInterface, frequency, width);
391 }
392 
393 bool
395 {
396  return GetLatestPhyEntity()->CanStartRx(ppdu);
397 }
398 
399 void
402 {
403  NS_LOG_FUNCTION(this << rxParams << interface);
404  Time rxDuration = rxParams->duration;
405  Ptr<SpectrumValue> receivedSignalPsd = rxParams->psd;
406  NS_LOG_DEBUG("Received signal with PSD " << *receivedSignalPsd << " and duration "
407  << rxDuration.As(Time::NS));
408  uint32_t senderNodeId = 0;
409  if (rxParams->txPhy)
410  {
411  senderNodeId = rxParams->txPhy->GetDevice()->GetNode()->GetId();
412  }
413  NS_LOG_DEBUG("Received signal from " << senderNodeId << " with unfiltered power "
414  << WToDbm(Integral(*receivedSignalPsd)) << " dBm");
415 
416  // Integrate over our receive bandwidth (i.e., all that the receive
417  // spectral mask representing our filtering allows) to find the
418  // total energy apparent to the "demodulator".
419  // This is done per 20 MHz channel band.
420  const auto channelWidth = interface ? interface->GetChannelWidth() : GetChannelWidth();
421  const auto& bands =
422  interface ? interface->GetBands() : m_currentSpectrumPhyInterface->GetBands();
423  double totalRxPowerW = 0;
424  RxPowerWattPerChannelBand rxPowerW;
425 
426  std::size_t index = 0;
427  uint16_t prevBw = 0;
428  for (const auto& band : bands)
429  {
430  uint16_t bw = (band.frequencies.second - band.frequencies.first) / 1e6;
431  NS_ASSERT(bw <= channelWidth);
432  index = ((bw != prevBw) ? 0 : (index + 1));
433  double rxPowerPerBandW =
434  WifiSpectrumValueHelper::GetBandPowerW(receivedSignalPsd, band.indices);
435  NS_LOG_DEBUG("Signal power received (watts) before antenna gain for "
436  << bw << " MHz channel band " << index << ": " << band);
437  rxPowerPerBandW *= DbToRatio(GetRxGain());
438  rxPowerW.insert({band, rxPowerPerBandW});
439  NS_LOG_DEBUG("Signal power received after antenna gain for "
440  << bw << " MHz channel band " << index << ": " << rxPowerPerBandW << " W ("
441  << WToDbm(rxPowerPerBandW) << " dBm)");
442  if (bw <= 20)
443  {
444  totalRxPowerW += rxPowerPerBandW;
445  }
446  prevBw = bw;
447  }
448 
450  {
451  const auto& heRuBands =
452  interface ? interface->GetHeRuBands() : m_currentSpectrumPhyInterface->GetHeRuBands();
453  NS_ASSERT(!heRuBands.empty());
454  for (const auto& [band, ru] : heRuBands)
455  {
456  double rxPowerPerBandW =
457  WifiSpectrumValueHelper::GetBandPowerW(receivedSignalPsd, band.indices);
458  NS_LOG_DEBUG("Signal power received (watts) before antenna gain for RU with type "
459  << ru.GetRuType() << " and index " << ru.GetIndex() << " -> ("
460  << band.indices.first << "; " << band.indices.second
461  << "): " << rxPowerPerBandW);
462  rxPowerPerBandW *= DbToRatio(GetRxGain());
463  NS_LOG_DEBUG("Signal power received after antenna gain for RU with type "
464  << ru.GetRuType() << " and index " << ru.GetIndex() << " -> ("
465  << band.indices.first << "; " << band.indices.second << "): "
466  << rxPowerPerBandW << " W (" << WToDbm(rxPowerPerBandW) << " dBm)");
467  rxPowerW.insert({band, rxPowerPerBandW});
468  }
469  }
470 
471  NS_LOG_DEBUG("Total signal power received after antenna gain: "
472  << totalRxPowerW << " W (" << WToDbm(totalRxPowerW) << " dBm)");
473 
474  Ptr<WifiSpectrumSignalParameters> wifiRxParams =
475  DynamicCast<WifiSpectrumSignalParameters>(rxParams);
476 
477  // Log the signal arrival to the trace source
478  m_signalCb(bool(wifiRxParams), senderNodeId, WToDbm(totalRxPowerW), rxDuration);
479 
480  if (!wifiRxParams)
481  {
482  NS_LOG_INFO("Received non Wi-Fi signal");
483  m_interference->AddForeignSignal(rxDuration, rxPowerW);
484  SwitchMaybeToCcaBusy(nullptr);
485  return;
486  }
487 
488  if (wifiRxParams && m_disableWifiReception)
489  {
490  NS_LOG_INFO("Received Wi-Fi signal but blocked from syncing");
491  m_interference->AddForeignSignal(rxDuration, rxPowerW);
492  SwitchMaybeToCcaBusy(nullptr);
493  return;
494  }
495 
496  if (m_trackSignalsInactiveInterfaces && interface &&
497  (interface != m_currentSpectrumPhyInterface))
498  {
499  NS_LOG_INFO("Received Wi-Fi signal from a non-active PHY interface");
500  m_interference->AddForeignSignal(rxDuration, rxPowerW);
501  SwitchMaybeToCcaBusy(nullptr);
502  return;
503  }
504 
505  // Do no further processing if signal is too weak
506  // Current implementation assumes constant RX power over the PPDU duration
507  // Compare received TX power per MHz to normalized RX sensitivity
508  const auto ppdu = GetRxPpduFromTxPpdu(wifiRxParams->ppdu);
509  if (totalRxPowerW < DbmToW(GetRxSensitivity()) * (ppdu->GetTxChannelWidth() / 20.0))
510  {
511  NS_LOG_INFO("Received signal too weak to process: " << WToDbm(totalRxPowerW) << " dBm");
512  m_interference->Add(ppdu, rxDuration, rxPowerW);
513  SwitchMaybeToCcaBusy(nullptr);
514  return;
515  }
516 
517  if (wifiRxParams->txPhy)
518  {
519  if (!CanStartRx(ppdu))
520  {
521  NS_LOG_INFO("Cannot start reception of the PPDU, consider it as interference");
522  m_interference->Add(ppdu, rxDuration, rxPowerW);
523  SwitchMaybeToCcaBusy(ppdu);
524  return;
525  }
526  }
527 
528  NS_LOG_INFO("Received Wi-Fi signal");
529  StartReceivePreamble(ppdu, rxPowerW, rxDuration);
530 }
531 
534 {
535  return GetPhyEntityForPpdu(ppdu)->GetRxPpduFromTxPpdu(ppdu);
536 }
537 
540 {
541  return m_antenna;
542 }
543 
544 void
546 {
547  NS_LOG_FUNCTION(this << a);
548  m_antenna = a;
549 }
550 
551 void
553 {
554  NS_LOG_FUNCTION(this << device);
555  WifiPhy::SetDevice(device);
556  for (auto& spectrumPhyInterface : m_spectrumPhyInterfaces)
557  {
558  spectrumPhyInterface.second->SetDevice(device);
559  }
560 }
561 
562 void
564 {
565  NS_LOG_FUNCTION(this << ppdu);
566  GetPhyEntity(ppdu->GetModulation())->StartTx(ppdu);
567 }
568 
569 void
571 {
572  NS_LOG_FUNCTION(this << txParams);
574  m_currentSpectrumPhyInterface->StartTx(txParams);
575 }
576 
577 uint16_t
578 SpectrumWifiPhy::GetGuardBandwidth(uint16_t currentChannelWidth) const
579 {
580  uint16_t guardBandwidth = 0;
581  if (currentChannelWidth == 22)
582  {
583  // handle case of DSSS transmission
584  guardBandwidth = 10;
585  }
586  else
587  {
588  // In order to properly model out of band transmissions for OFDM, the guard
589  // band has been configured so as to expand the modeled spectrum up to the
590  // outermost referenced point in "Transmit spectrum mask" sections' PSDs of
591  // each PHY specification of 802.11-2016 standard. It thus ultimately corresponds
592  // to the currently considered channel bandwidth (which can be different from
593  // supported channel width).
594  guardBandwidth = currentChannelWidth;
595  }
596  return guardBandwidth;
597 }
598 
601  uint16_t bandWidth,
602  uint8_t bandIndex /* = 0 */)
603 {
604  const auto subcarrierSpacing = GetSubcarrierSpacing();
605  const auto channelWidth = spectrumPhyInterface->GetChannelWidth();
606  const auto numBandsInBand = static_cast<size_t>(bandWidth * 1e6 / subcarrierSpacing);
607  auto numBandsInChannel = static_cast<size_t>(channelWidth * 1e6 / subcarrierSpacing);
608  if (numBandsInBand % 2 == 0)
609  {
610  numBandsInChannel += 1; // symmetry around center frequency
611  }
612  auto rxSpectrumModel = spectrumPhyInterface->GetRxSpectrumModel();
613  size_t totalNumBands = rxSpectrumModel->GetNumBands();
614  NS_ASSERT_MSG((numBandsInChannel % 2 == 1) && (totalNumBands % 2 == 1),
615  "Should have odd number of bands");
616  NS_ASSERT_MSG((bandIndex * bandWidth) < channelWidth, "Band index is out of bound");
617  NS_ASSERT(totalNumBands >= numBandsInChannel);
618  auto startIndex = ((totalNumBands - numBandsInChannel) / 2) + (bandIndex * numBandsInBand);
619  auto stopIndex = startIndex + numBandsInBand - 1;
620  auto frequencies =
621  ConvertIndicesToFrequenciesForInterface(spectrumPhyInterface, {startIndex, stopIndex});
622  auto freqRange = spectrumPhyInterface->GetFrequencyRange();
623  NS_ASSERT(frequencies.first >= (freqRange.minFrequency * 1e6));
624  NS_ASSERT(frequencies.second <= (freqRange.maxFrequency * 1e6));
625  NS_ASSERT((frequencies.second - frequencies.first) == (bandWidth * 1e6));
626  if (startIndex >= totalNumBands / 2)
627  {
628  // step past DC
629  startIndex += 1;
630  }
631  return {{startIndex, stopIndex}, frequencies};
632 }
633 
635 SpectrumWifiPhy::GetBand(uint16_t bandWidth, uint8_t bandIndex /* = 0 */)
636 {
638  return GetBandForInterface(m_currentSpectrumPhyInterface, bandWidth, bandIndex);
639 }
640 
643 {
646 }
647 
650  Ptr<WifiSpectrumPhyInterface> spectrumPhyInterface,
651  const WifiSpectrumBandIndices& indices) const
652 {
653  NS_ABORT_IF(!spectrumPhyInterface);
654  auto rxSpectrumModel = spectrumPhyInterface->GetRxSpectrumModel();
655  auto startGuardBand = rxSpectrumModel->Begin();
656  auto startChannel = std::next(startGuardBand, indices.first);
657  auto endChannel = std::next(startGuardBand, indices.second + 1);
658  auto lowFreq = static_cast<uint64_t>(startChannel->fc);
659  auto highFreq = static_cast<uint64_t>(endChannel->fc);
660  return {lowFreq, highFreq};
661 }
662 
663 std::tuple<double, double, double>
665 {
666  return std::make_tuple(m_txMaskInnerBandMinimumRejection,
669 }
670 
673 {
675  return m_currentSpectrumPhyInterface->GetFrequencyRange();
676 }
677 
678 const std::map<FrequencyRange, Ptr<WifiSpectrumPhyInterface>>&
680 {
682 }
683 
685 SpectrumWifiPhy::GetInterfaceCoveringChannelBand(uint16_t frequency, uint16_t width) const
686 {
687  const auto lowFreq = frequency - (width / 2);
688  const auto highFreq = frequency + (width / 2);
689  const auto it = std::find_if(m_spectrumPhyInterfaces.cbegin(),
691  [lowFreq, highFreq](const auto& item) {
692  return ((lowFreq >= item.first.minFrequency) &&
693  (highFreq <= item.first.maxFrequency));
694  });
695  if (it == std::end(m_spectrumPhyInterfaces))
696  {
697  return nullptr;
698  }
699  return it->second;
700 }
701 
704 {
706 }
707 
708 void
710 {
711  m_channelSwitchedCallback = callback;
712 }
713 
714 } // namespace ns3
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:575
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
static WifiSpectrumBandIndices ConvertHeRuSubcarriers(uint16_t bandWidth, uint16_t guardBandwidth, uint32_t subcarrierSpacing, HeRu::SubcarrierRange subcarrierRange, uint8_t bandIndex=0)
Definition: he-phy.cc:1819
RU Specification.
Definition: he-ru.h:66
std::size_t GetPhyIndex(uint16_t bw, uint8_t p20Index) const
Get the RU PHY index.
Definition: he-ru.cc:475
static SubcarrierGroup GetSubcarrierGroup(uint16_t 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:587
static std::size_t GetNRus(uint16_t 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:491
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
Definition: he-ru.h:55
std::pair< int16_t, int16_t > SubcarrierRange
(lowest index, highest index) pair defining a subcarrier range
Definition: he-ru.h:52
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:41
@ RU_2x996_TONE
Definition: he-ru.h:48
bool IsInitialized() const
Check if the object has been initialized.
Definition: object.cc:212
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
virtual Ptr< NetDevice > GetDevice() const =0
Get the associated NetDevice instance.
802.11 PHY layer model
TracedCallback< bool, uint32_t, double, Time > m_signalCb
Signal callback.
std::tuple< double, double, double > GetTxMaskRejectionParams() const override
void ResetSpectrumModel(Ptr< WifiSpectrumPhyInterface > spectrumPhyInterface, uint16_t centerFrequency, uint16_t channelWidth)
Perform run-time spectrum model change.
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 ...
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.
HeRuBands GetHeRuBands(Ptr< WifiSpectrumPhyInterface > spectrumPhyInterface, uint16_t guardBandwidth)
This function computes the RU bands that belong to a given spectrum PHY interface.
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.
Ptr< AntennaModel > m_antenna
antenna model
FrequencyRange GetCurrentFrequencyRange() const override
Get the frequency range of the current RF interface.
void ConfigureInterface(uint16_t frequency, uint16_t width)
Configure a non-active spectrum PHY interface to operate on a given frequency with a given width.
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.
Ptr< WifiSpectrumPhyInterface > GetInterfaceCoveringChannelBand(uint16_t frequency, uint16_t 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.
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.
double m_txMaskInnerBandMinimumRejection
The minimum rejection (in dBr) for the inner band of the transmit spectrum mask.
bool m_trackSignalsInactiveInterfaces
flag whether signals coming from inactive spectrum PHY interfaces are tracked
double m_txMaskOuterBandMinimumRejection
The minimum rejection (in dBr) for the outer band of the transmit spectrum mask.
void DoDispose() override
Destructor implementation.
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const override
WifiSpectrumBandInfo GetBandForInterface(Ptr< WifiSpectrumPhyInterface > spectrumPhyInterface, uint16_t bandWidth, uint8_t bandIndex=0)
Get the info of a given band that belongs to a given spectrum PHY interface.
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.
Callback< void > m_channelSwitchedCallback
Callback when channel switched.
void SetAntenna(const Ptr< AntennaModel > antenna)
double m_txMaskOuterBandMaximumRejection
The maximum rejection (in dBr) for the outer band of the transmit spectrum mask.
WifiSpectrumBandInfo GetBand(uint16_t bandWidth, uint8_t bandIndex=0) override
Get the info of a given band.
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
void NotifyChannelSwitched()
Notify the spectrum channel has switched.
void DoChannelSwitch() override
Actually switch channel based on the stored channel settings.
WifiSpectrumBandFrequencies ConvertIndicesToFrequencies(const WifiSpectrumBandIndices &indices) const override
This is a helper function to convert start and stop indices to start and stop frequencies.
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
@ NS
nanosecond
Definition: nstime.h:119
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
802.11 PHY layer model
Definition: wifi-phy.h:53
uint32_t GetSubcarrierSpacing() const
Definition: wifi-phy.cc:2251
uint16_t GetChannelWidth() const
Definition: wifi-phy.cc:1051
double GetRxSensitivity() const
Return the receive sensitivity threshold (dBm).
Definition: wifi-phy.cc:486
uint16_t GetFrequency() const
Definition: wifi-phy.cc:1039
double GetRxGain() const
Return the reception gain (dB).
Definition: wifi-phy.cc:588
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:711
virtual void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-phy.cc:607
void StartReceivePreamble(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW, Time rxDuration)
Start receiving the PHY preamble of a PPDU (i.e.
Definition: wifi-phy.cc:1868
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition: wifi-phy.cc:613
void DoDispose() override
Destructor implementation.
Definition: wifi-phy.cc:408
virtual void DoChannelSwitch()
Actually switch channel based on the stored channel settings.
Definition: wifi-phy.cc:1174
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:2105
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1260
void DoInitialize() override
Initialize() implementation.
Definition: wifi-phy.cc:383
WifiStandard GetStandard() const
Get the configured Wi-Fi standard.
Definition: wifi-phy.cc:1027
Ptr< PhyEntity > GetPhyEntityForPpdu(const Ptr< const WifiPpdu > ppdu) const
Get the supported PHY entity to use for a received PPDU.
Definition: wifi-phy.cc:732
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1033
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition: wifi-phy.cc:726
bool IsSet() const
Return true if a valid channel has been set, false otherwise.
uint8_t GetPrimaryChannelIndex(uint16_t primaryChannelWidth) const
If the operating channel width is a multiple of 20 MHz, return the index of the primary channel of th...
static double GetBandPowerW(Ptr< SpectrumValue > psd, const WifiSpectrumBandIndices &band)
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: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_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#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_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
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.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
double WToDbm(double w)
Convert from Watts to dBm.
Definition: wifi-utils.cc:46
std::pair< uint64_t, uint64_t > WifiSpectrumBandFrequencies
typedef for a pair of start and stop frequencies in Hz to represent a band
double Integral(const SpectrumValue &arg)
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:40
std::vector< WifiSpectrumBandInfo > WifiSpectrumBands
vector of spectrum bands
std::pair< uint32_t, uint32_t > WifiSpectrumBandIndices
typedef for a pair of start and stop sub-band indices
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43
std::map< WifiSpectrumBandInfo, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Definition: phy-entity.h:77
std::map< WifiSpectrumBandInfo, HeRu::RuSpec > HeRuBands
Map a spectrum band associated with an RU to the RU specification.
double DbToRatio(double dB)
Convert from dB to ratio.
Definition: wifi-utils.cc:34
channel
Definition: third.py:88
Struct defining a frequency range between minFrequency (MHz) and maxFrequency (MHz).
Time duration
The duration of the packet transmission.
Ptr< SpectrumPhy > txPhy
The SpectrumPhy instance that is making the transmission.
Ptr< SpectrumValue > psd
The Power Spectral Density of the waveform, in linear units.
WifiSpectrumBandInfo structure containing info about a spectrum band.