From c03e501e778e983ca451c9173a69bae247e808e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Sun, 15 Jan 2023 09:29:22 +0100 Subject: [PATCH] wifi: PPDU can be transmitted over multiple center frequencies (one per segment) This will be a single one except for 80+80MHz when supported --- src/wifi/model/phy-entity.cc | 2 +- src/wifi/model/wifi-bandwidth-filter.cc | 2 +- src/wifi/model/wifi-ppdu.cc | 63 ++++++++++++++++++++----- src/wifi/model/wifi-ppdu.h | 10 ++-- 4 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/wifi/model/phy-entity.cc b/src/wifi/model/phy-entity.cc index f1f4472c7..2a9224a2a 100644 --- a/src/wifi/model/phy-entity.cc +++ b/src/wifi/model/phy-entity.cc @@ -1386,7 +1386,7 @@ PhyEntity::CanStartRx(Ptr ppdu) const m_wifiPhy->GetOperatingChannel().GetPrimaryChannelCenterFrequency(primaryWidth); const auto p20MinFreq = p20CenterFreq - (primaryWidth / 2); const auto p20MaxFreq = p20CenterFreq + (primaryWidth / 2); - const auto txCenterFreq = ppdu->GetTxCenterFreq(); + const auto txCenterFreq = ppdu->GetTxCenterFreqs().front(); const auto txChannelWidth = ppdu->GetTxChannelWidth(); const auto minTxFreq = txCenterFreq - txChannelWidth / 2; const auto maxTxFreq = txCenterFreq + txChannelWidth / 2; diff --git a/src/wifi/model/wifi-bandwidth-filter.cc b/src/wifi/model/wifi-bandwidth-filter.cc index 307a8c6b2..c760f4956 100644 --- a/src/wifi/model/wifi-bandwidth-filter.cc +++ b/src/wifi/model/wifi-bandwidth-filter.cc @@ -89,7 +89,7 @@ WifiBandwidthFilter::DoFilter(Ptr params, // The signal power is spread over a frequency interval that includes a guard // band on the left and a guard band on the right of the nominal TX band - const auto rxCenterFreq = wifiRxParams->ppdu->GetTxCenterFreq(); + const auto rxCenterFreq = wifiRxParams->ppdu->GetTxCenterFreqs().front(); const auto rxWidth = wifiRxParams->ppdu->GetTxVector().GetChannelWidth(); const auto guardBandwidth = wifiPhy->GetGuardBandwidth(rxWidth); const auto operatingFrequency = interface->GetCenterFrequency(); diff --git a/src/wifi/model/wifi-ppdu.cc b/src/wifi/model/wifi-ppdu.cc index 176032ac3..97785142f 100644 --- a/src/wifi/model/wifi-ppdu.cc +++ b/src/wifi/model/wifi-ppdu.cc @@ -24,6 +24,49 @@ #include "ns3/log.h" +namespace +{ +/** + * Get the center frequency (in MHz) of each segment covered by the provided channel width (in + * MHz). If the specified channel width is contained in a single frequency segment, a single + * center frequency is returned. If the specified channel width is spread over multiple + * frequency segments (e.g. 160 MHz if operating channel is 80+80MHz), multiple center + * frequencies are returned. + * + * \param channel the operating channel of the PHY + * \param channelWidth the channel width in MHz + * \return the center frequency (in MHz) of each segment covered by the given width + */ +std::vector +GetChannelCenterFrequenciesPerSegment(const ns3::WifiPhyOperatingChannel& channel, + ns3::ChannelWidthMhz channelWidth) +{ + if (!channel.IsSet()) + { + return {}; + } + std::vector freqs{}; + const auto width = std::min(channelWidth, channel.GetWidth(0)); + const auto primarySegmentIndex = channel.GetPrimarySegmentIndex(width); + const auto secondarySegmentIndex = channel.GetSecondarySegmentIndex(width); + const auto primaryIndex = channel.GetPrimaryChannelIndex(channelWidth); + const auto segmentIndices = + ((channel.GetNSegments() < 2) || (channelWidth <= channel.GetWidth(primarySegmentIndex))) + ? std::vector{primarySegmentIndex} + : std::vector{primarySegmentIndex, secondarySegmentIndex}; + for (auto segmentIndex : segmentIndices) + { + const auto segmentFrequency = channel.GetFrequency(segmentIndex); + const auto segmentWidth = channel.GetWidth(segmentIndex); + const auto segmentOffset = (primarySegmentIndex * (segmentWidth / channelWidth)); + const auto freq = + segmentFrequency - (segmentWidth / 2.) + (primaryIndex - segmentOffset + 0.5) * width; + freqs.push_back(freq); + } + return freqs; +} +} // namespace + namespace ns3 { @@ -35,9 +78,7 @@ WifiPpdu::WifiPpdu(Ptr psdu, uint64_t uid /* = UINT64_MAX */) : m_preamble(txVector.GetPreambleType()), m_modulation(txVector.IsValid() ? txVector.GetModulationClass() : WIFI_MOD_CLASS_UNKNOWN), - m_txCenterFreq(channel.IsSet() - ? channel.GetPrimaryChannelCenterFrequency(txVector.GetChannelWidth()) - : 0), + m_txCenterFreqs(GetChannelCenterFrequenciesPerSegment(channel, txVector.GetChannelWidth())), m_uid(uid), m_txVector(txVector), m_operatingChannel(channel), @@ -57,9 +98,7 @@ WifiPpdu::WifiPpdu(const WifiConstPsduMap& psdus, : m_preamble(txVector.GetPreambleType()), m_modulation(txVector.IsValid() ? txVector.GetMode(psdus.begin()->first).GetModulationClass() : WIFI_MOD_CLASS_UNKNOWN), - m_txCenterFreq(channel.IsSet() - ? channel.GetPrimaryChannelCenterFrequency(txVector.GetChannelWidth()) - : 0), + m_txCenterFreqs(GetChannelCenterFrequenciesPerSegment(channel, txVector.GetChannelWidth())), m_uid(uid), m_txVector(txVector), m_operatingChannel(channel), @@ -148,18 +187,18 @@ WifiPpdu::GetTxChannelWidth() const return m_txChannelWidth; } -uint16_t -WifiPpdu::GetTxCenterFreq() const +std::vector +WifiPpdu::GetTxCenterFreqs() const { - return m_txCenterFreq; + return m_txCenterFreqs; } bool WifiPpdu::DoesOverlapChannel(uint16_t minFreq, uint16_t maxFreq) const { - NS_LOG_FUNCTION(this << m_txCenterFreq << minFreq << maxFreq); - uint16_t minTxFreq = m_txCenterFreq - m_txChannelWidth / 2; - uint16_t maxTxFreq = m_txCenterFreq + m_txChannelWidth / 2; + NS_LOG_FUNCTION(this << m_txCenterFreqs.front() << minFreq << maxFreq); + uint16_t minTxFreq = m_txCenterFreqs.front() - m_txChannelWidth / 2; + uint16_t maxTxFreq = m_txCenterFreqs.front() + m_txChannelWidth / 2; /** * The PPDU does not overlap the channel in two cases. * diff --git a/src/wifi/model/wifi-ppdu.h b/src/wifi/model/wifi-ppdu.h index 861ea585e..8dffd7fab 100644 --- a/src/wifi/model/wifi-ppdu.h +++ b/src/wifi/model/wifi-ppdu.h @@ -27,6 +27,7 @@ #include #include #include +#include /** * \file @@ -137,9 +138,9 @@ class WifiPpdu : public SimpleRefCount virtual ChannelWidthMhz GetTxChannelWidth() const; /** - * \return the center frequency (MHz) used for the transmission of this PPDU + * \return the center frequency per segment (MHz) used for the transmission of this PPDU */ - uint16_t GetTxCenterFreq() const; + std::vector GetTxCenterFreqs() const; /** * Check whether the given PPDU overlaps a given channel. @@ -202,8 +203,9 @@ class WifiPpdu : public SimpleRefCount WifiPreamble m_preamble; //!< the PHY preamble WifiModulationClass m_modulation; //!< the modulation used for the transmission of this PPDU WifiConstPsduMap m_psdus; //!< the PSDUs contained in this PPDU - uint16_t m_txCenterFreq; //!< the center frequency (MHz) used for the transmission of this PPDU - uint64_t m_uid; //!< the unique ID of this PPDU + std::vector m_txCenterFreqs; //!< the center frequency (MHz) per segment used for the + //!< transmission of this PPDU + uint64_t m_uid; //!< the unique ID of this PPDU mutable std::optional m_txVector; //!< the TXVECTOR at TX PHY or the reconstructed TXVECTOR at RX PHY (or //!< std::nullopt if TXVECTOR has not been reconstructed yet)