diff --git a/src/wifi/model/wifi-tx-vector.cc b/src/wifi/model/wifi-tx-vector.cc index 669f662a1..02931cbbf 100644 --- a/src/wifi/model/wifi-tx-vector.cc +++ b/src/wifi/model/wifi-tx-vector.cc @@ -48,6 +48,7 @@ WifiTxVector::WifiTxVector() m_modeInitialized(false), m_inactiveSubchannels(), m_ruAllocation(), + m_center26ToneRuIndication(std::nullopt), m_ehtPpduType(1) // SU transmission by default { } @@ -83,6 +84,7 @@ WifiTxVector::WifiTxVector(WifiMode mode, m_modeInitialized(true), m_inactiveSubchannels(), m_ruAllocation(), + m_center26ToneRuIndication(std::nullopt), m_ehtPpduType(1) // SU transmission by default { } @@ -106,6 +108,7 @@ WifiTxVector::WifiTxVector(const WifiTxVector& txVector) m_inactiveSubchannels(txVector.m_inactiveSubchannels), m_sigBMcs(txVector.m_sigBMcs), m_ruAllocation(txVector.m_ruAllocation), + m_center26ToneRuIndication(txVector.m_center26ToneRuIndication), m_ehtPpduType(txVector.m_ehtPpduType) { m_muUserInfos.clear(); @@ -596,6 +599,30 @@ WifiTxVector::GetInactiveSubchannels() const return m_inactiveSubchannels; } +void +WifiTxVector::SetCenter26ToneRuIndication(Center26ToneRuIndication center26ToneRuIndication) +{ + if (IsDlMu()) + { + NS_ASSERT(center26ToneRuIndication == DeriveCenter26ToneRuIndication()); + } + m_center26ToneRuIndication = center26ToneRuIndication; +} + +std::optional +WifiTxVector::GetCenter26ToneRuIndication() const +{ + if (!IsDlMu() || (m_channelWidth < 80)) + { + return std::nullopt; + } + if (!m_center26ToneRuIndication.has_value()) + { + m_center26ToneRuIndication.emplace(DeriveCenter26ToneRuIndication()); + } + return m_center26ToneRuIndication; +} + std::ostream& operator<<(std::ostream& os, const WifiTxVector& v) { @@ -770,4 +797,21 @@ WifiTxVector::DeriveRuAllocation() const return ruAllocations; } +Center26ToneRuIndication +WifiTxVector::DeriveCenter26ToneRuIndication() const +{ + uint8_t center26ToneRuIndication{0}; + for (const auto& userInfo : m_muUserInfos) + { + if ((userInfo.second.ru.GetRuType() == HeRu::RU_26_TONE) && + (userInfo.second.ru.GetIndex() == 19)) + { + center26ToneRuIndication |= (userInfo.second.ru.GetPrimary80MHz()) + ? CENTER_26_TONE_RU_LOW_80_MHZ_ALLOCATED + : CENTER_26_TONE_RU_HIGH_80_MHZ_ALLOCATED; + } + } + return static_cast(center26ToneRuIndication); +} + } // namespace ns3 diff --git a/src/wifi/model/wifi-tx-vector.h b/src/wifi/model/wifi-tx-vector.h index 472155a2a..c00eb8e99 100644 --- a/src/wifi/model/wifi-tx-vector.h +++ b/src/wifi/model/wifi-tx-vector.h @@ -27,6 +27,7 @@ #include "ns3/he-ru.h" #include +#include #include namespace ns3 @@ -67,6 +68,19 @@ using ContentChannelAllocation = std::vector>; /// 8 bit RU_ALLOCATION per 20 MHz using RuAllocation = std::vector; +/** + * \ingroup wifi + * Enum for the different values for CENTER_26_TONE_RU + */ +enum Center26ToneRuIndication : uint8_t +{ + CENTER_26_TONE_RU_UNALLOCATED = 0, + CENTER_26_TONE_RU_LOW_80_MHZ_ALLOCATED, /* also used if BW == 80 MHz */ + CENTER_26_TONE_RU_HIGH_80_MHZ_ALLOCATED, /* unused if BW < 160 MHz */ + CENTER_26_TONE_RU_LOW_AND_HIGH_80_MHZ_ALLOCATED, /* unused if BW < 160 MHz */ + CENTER_26_TONE_RU_INDICATION_MAX /* last value */ +}; + /** * This class mimics the TXVECTOR which is to be * passed to the PHY in order to define the parameters which are to be @@ -448,13 +462,13 @@ class WifiTxVector WifiMode GetSigBMode() const; /** - * Set RU Allocation of SIG-B common field + * Set RU_ALLOCATION field * \param ruAlloc 8 bit RU_ALLOCATION per 20 MHz */ void SetRuAllocation(const RuAllocation& ruAlloc); /** - * Get RU Allocation of SIG-B + * Get RU_ALLOCATION field * \return 8 bit RU_ALLOCATION per 20 MHz */ const RuAllocation& GetRuAllocation() const; @@ -466,6 +480,20 @@ class WifiTxVector */ ContentChannelAllocation GetContentChannelAllocation() const; + /** + * Set CENTER_26_TONE_RU field + * \param center26ToneRuIndication the CENTER_26_TONE_RU field + */ + void SetCenter26ToneRuIndication(Center26ToneRuIndication center26ToneRuIndication); + + /** + * Get CENTER_26_TONE_RU field + * This field is present if format is HE_MU and + * when channel width is set to 80 MHz or larger. + * \return the CENTER_26_TONE_RU field if present + */ + std::optional GetCenter26ToneRuIndication() const; + /** * Set the EHT_PPDU_TYPE parameter * \param type the EHT_PPDU_TYPE parameter @@ -479,13 +507,24 @@ class WifiTxVector private: /** - * Derive the RU allocation from the TXVECTOR for which its RU allocation has not been set yet. - * This is valid only for allocations of RUs of the same size. + * Derive the RU_ALLOCATION field from the TXVECTOR + * for which its RU_ALLOCATION field has not been set yet, + * based on the content of per-user information. + * This is valid only for allocations of RUs of the same size per 20 MHz subchannel. * - * \return the RU allocation + * \return 8 bit RU_ALLOCATION per 20 MHz */ RuAllocation DeriveRuAllocation() const; + /** + * Derive the CENTER_26_TONE_RU field from the TXVECTOR + * for which its CENTER_26_TONE_RU has not been set yet, + * based on the content of per-user information. + * + * \return the CENTER_26_TONE_RU field + */ + Center26ToneRuIndication DeriveCenter26ToneRuIndication() const; + WifiMode m_mode; /**< The DATARATE parameter in Table 15-4. It is the value that will be passed to PMD_RATE.request */ @@ -519,7 +558,13 @@ class WifiTxVector mutable RuAllocation m_ruAllocation; /**< RU allocations that are going to be carried in SIG-B common field per Table 27-1 IEEE */ - uint8_t m_ehtPpduType; /**< EHT_PPDU_TYPE per Table 36-1 IEEE 802.11be D2.3 */ + + mutable std::optional + m_center26ToneRuIndication; /**< CENTER_26_TONE_RU field when format is HE_MU and + when channel width is set to 80 MHz or larger (Table 27-1 + 802.11ax-2021)*/ + + uint8_t m_ehtPpduType; /**< EHT_PPDU_TYPE per Table 36-1 IEEE 802.11be D2.3 */ }; /**