34 #include "ns3/boolean.h"
35 #include "ns3/double.h"
36 #include "ns3/he-phy.h"
39 #include "ns3/simulator.h"
40 #include "ns3/spectrum-channel.h"
55 TypeId(
"ns3::SpectrumWifiPhy")
59 .AddAttribute(
"DisableWifiReception",
60 "Prevent Wi-Fi frame sync from ever happening",
65 "TrackSignalsFromInactiveInterfaces",
66 "Enable or disable tracking signals coming from inactive spectrum PHY interfaces",
71 "TxMaskInnerBandMinimumRejection",
72 "Minimum rejection (dBr) for the inner band of the transmit spectrum mask",
75 MakeDoubleChecker<double>())
77 "TxMaskOuterBandMinimumRejection",
78 "Minimum rejection (dBr) for the outer band of the transmit spectrum mask",
81 MakeDoubleChecker<double>())
83 "TxMaskOuterBandMaximumRejection",
84 "Maximum rejection (dBr) for the outer band of the transmit spectrum mask",
87 MakeDoubleChecker<double>())
88 .AddTraceSource(
"SignalArrival",
91 "ns3::SpectrumWifiPhy::SignalArrivalCallback");
96 : m_spectrumPhyInterfaces{},
97 m_currentSpectrumPhyInterface{nullptr}
130 const auto channelWidth = spectrumPhyInterface->GetChannelWidth();
131 if (channelWidth < 20)
137 for (uint16_t bw = 160; bw >= 20; bw = bw / 2)
139 for (uint32_t i = 0; i < (channelWidth / bw); ++i)
150 uint16_t guardBandwidth)
153 const auto channelWidth = spectrumPhyInterface->GetChannelWidth();
154 for (uint16_t bw = 160; bw >= 20; bw = bw / 2)
156 for (uint32_t i = 0; i < (channelWidth / bw); ++i)
162 for (std::size_t phyIndex = 1; phyIndex <= nRus; phyIndex++)
166 std::make_pair(group.front().first, group.back().second);
172 const auto bandFrequencies =
176 (bw == 160 && phyIndex > nRus / 2 ? phyIndex - nRus / 2 : phyIndex);
178 bool primary80IsLower80 = (p20Index < bw / 40);
180 (primary80IsLower80 && phyIndex <= nRus / 2) ||
181 (!primary80IsLower80 && phyIndex > nRus / 2));
184 heRuBands.insert({band, ru});
200 const auto channelWidth = spectrumPhyInterface->GetChannelWidth();
202 for (
const auto& bandRuPair : heRuBands)
204 allBands.push_back(bandRuPair.first);
206 spectrumPhyInterface->SetHeRuBands(std::move(heRuBands));
209 spectrumPhyInterface->SetBands(std::move(bands));
213 m_interference->UpdateBands(allBands, spectrumPhyInterface->GetFrequencyRange());
217 for (
const auto& band : allBands)
236 const auto foundOverlappingChannel =
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));
247 "Added a wifi spectrum channel that overlaps with another existing wifi "
250 auto wifiSpectrumPhyInterface = CreateObject<WifiSpectrumPhyInterface>(freqRange);
251 wifiSpectrumPhyInterface->SetSpectrumWifiPhy(
this);
252 wifiSpectrumPhyInterface->SetChannel(
channel);
255 wifiSpectrumPhyInterface->SetDevice(
GetDevice());
262 uint16_t centerFrequency,
263 uint16_t channelWidth)
265 NS_LOG_FUNCTION(
this << spectrumPhyInterface << centerFrequency << channelWidth);
276 spectrumPhyInterface->SetRxSpectrumModel(centerFrequency,
281 spectrumPhyInterface->GetChannel()->AddRx(spectrumPhyInterface);
295 if ((frequencyBefore == frequencyAfter) && (widthBefore == widthAfter))
309 "No spectrum channel covers frequency range ["
310 << frequencyAfter - (widthAfter / 2) <<
" MHz - "
311 << frequencyAfter + (widthAfter / 2) <<
" MHz]");
313 if (interfaceChanged)
315 NS_LOG_DEBUG(
"Switch to existing RF interface with frequency/width pair of ("
316 << frequencyAfter <<
", " << widthAfter <<
")");
369 NS_LOG_DEBUG(
"Tracking of signals on inactive interfaces is not enabled");
376 "No spectrum channel covers frequency range ["
377 << frequency - (width / 2) <<
" MHz - " << frequency + (width / 2)
381 "This method should not be called for the current interface");
383 if ((frequency == spectrumPhyInterface->GetCenterFrequency()) &&
384 (width == spectrumPhyInterface->GetChannelWidth()))
386 NS_LOG_DEBUG(
"Same RF channel as before on that interface, do nothing");
406 NS_LOG_DEBUG(
"Received signal with PSD " << *receivedSignalPsd <<
" and duration "
408 uint32_t senderNodeId = 0;
413 NS_LOG_DEBUG(
"Received signal from " << senderNodeId <<
" with unfiltered power "
423 double totalRxPowerW = 0;
426 std::size_t index = 0;
428 for (const auto& band : bands)
430 uint16_t bw = (band.frequencies.second - band.frequencies.first) / 1e6;
432 index = ((bw != prevBw) ? 0 : (index + 1));
433 double rxPowerPerBandW =
435 NS_LOG_DEBUG(
"Signal power received (watts) before antenna gain for "
436 << bw <<
" MHz channel band " << index <<
": " << band);
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)");
444 totalRxPowerW += rxPowerPerBandW;
451 const auto& heRuBands =
454 for (const auto& [band, ru] : heRuBands)
456 double rxPowerPerBandW =
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);
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});
471 NS_LOG_DEBUG(
"Total signal power received after antenna gain: "
472 << totalRxPowerW <<
" W (" <<
WToDbm(totalRxPowerW) <<
" dBm)");
475 DynamicCast<WifiSpectrumSignalParameters>(rxParams);
478 m_signalCb(
bool(wifiRxParams), senderNodeId,
WToDbm(totalRxPowerW), rxDuration);
490 NS_LOG_INFO(
"Received Wi-Fi signal but blocked from syncing");
499 NS_LOG_INFO(
"Received Wi-Fi signal from a non-active PHY interface");
511 NS_LOG_INFO(
"Received signal too weak to process: " <<
WToDbm(totalRxPowerW) <<
" dBm");
517 if (wifiRxParams->txPhy)
521 NS_LOG_INFO(
"Cannot start reception of the PPDU, consider it as interference");
558 spectrumPhyInterface.second->SetDevice(device);
580 uint16_t guardBandwidth = 0;
581 if (currentChannelWidth == 22)
594 guardBandwidth = currentChannelWidth;
596 return guardBandwidth;
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)
610 numBandsInChannel += 1;
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;
622 auto freqRange = spectrumPhyInterface->GetFrequencyRange();
626 if (startIndex >= totalNumBands / 2)
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};
663 std::tuple<double, double, double>
678 const std::map<FrequencyRange, Ptr<WifiSpectrumPhyInterface>>&
687 const auto lowFreq = frequency - (width / 2);
688 const auto highFreq = frequency + (width / 2);
691 [lowFreq, highFreq](
const auto& item) {
692 return ((lowFreq >= item.first.minFrequency) &&
693 (highFreq <= item.first.maxFrequency));
void Nullify()
Discard the implementation, set it to null.
bool IsNull() const
Check for null implementation.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
static WifiSpectrumBandIndices ConvertHeRuSubcarriers(uint16_t bandWidth, uint16_t guardBandwidth, uint32_t subcarrierSpacing, HeRu::SubcarrierRange subcarrierRange, uint8_t bandIndex=0)
std::size_t GetPhyIndex(uint16_t bw, uint8_t p20Index) const
Get the RU PHY index.
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...
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...
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
std::pair< int16_t, int16_t > SubcarrierRange
(lowest index, highest index) pair defining a subcarrier range
RuType
The different HE Resource Unit (RU) types.
bool IsInitialized() const
Check if the object has been initialized.
Smart pointer class similar to boost::intrusive_ptr.
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
virtual Ptr< NetDevice > GetDevice() const =0
Get the associated NetDevice instance.
~SpectrumWifiPhy() override
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.
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
uint32_t GetSubcarrierSpacing() const
uint16_t GetChannelWidth() const
double GetRxSensitivity() const
Return the receive sensitivity threshold (dBm).
uint16_t GetFrequency() const
double GetRxGain() const
Return the reception gain (dB).
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
virtual void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
void StartReceivePreamble(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW, Time rxDuration)
Start receiving the PHY preamble of a PPDU (i.e.
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
void DoDispose() override
Destructor implementation.
virtual void DoChannelSwitch()
Actually switch channel based on the stored channel settings.
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.
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
void DoInitialize() override
Initialize() implementation.
WifiStandard GetStandard() const
Get the configured Wi-Fi standard.
Ptr< PhyEntity > GetPhyEntityForPpdu(const Ptr< const WifiPpdu > ppdu) const
Get the supported PHY entity to use for a received PPDU.
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
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,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#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.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
double WToDbm(double w)
Convert from Watts to dBm.
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.
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)
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
std::map< WifiSpectrumBandInfo, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
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.
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.