diff --git a/src/wifi/model/he/he-ru.cc b/src/wifi/model/he/he-ru.cc index e1e95e038..740468c19 100644 --- a/src/wifi/model/he/he-ru.cc +++ b/src/wifi/model/he/he-ru.cc @@ -157,7 +157,8 @@ HeRu::RuSpec::RuSpec () HeRu::RuSpec::RuSpec (RuType ruType, std::size_t index, bool primary80MHz) : m_ruType (ruType), m_index (index), - m_primary80MHz (primary80MHz) + m_primary80MHz (primary80MHz), + m_phyIndex (0) { NS_ABORT_MSG_IF (index == 0, "Index cannot be zero"); } @@ -183,6 +184,37 @@ HeRu::RuSpec::GetPrimary80MHz (void) const return m_primary80MHz; } +void +HeRu::RuSpec::SetPhyIndex (uint16_t bw, uint8_t p20Index) +{ + bool primary80IsLower80 = (p20Index < bw / 40); + + if (bw < 160 + || m_ruType == HeRu::RU_2x996_TONE + || (primary80IsLower80 && m_primary80MHz) + || (!primary80IsLower80 && !m_primary80MHz)) + { + m_phyIndex = m_index; + } + else + { + m_phyIndex = m_index + GetNRus (bw, m_ruType) / 2; + } +} + +bool +HeRu::RuSpec::IsPhyIndexSet (void) const +{ + return (m_phyIndex != 0); +} + +std::size_t +HeRu::RuSpec::GetPhyIndex (void) const +{ + NS_ABORT_MSG_IF (m_phyIndex == 0, "RU PHY index not set"); + return m_phyIndex; +} + std::size_t HeRu::GetNRus (uint16_t bw, RuType ruType) { @@ -431,7 +463,12 @@ std::ostream& operator<< (std::ostream& os, const HeRu::RuType &ruType) std::ostream& operator<< (std::ostream& os, const HeRu::RuSpec &ru) { - os << "RU{" << ru.GetRuType () << "/" << ru.GetIndex () << "/" << (ru.GetPrimary80MHz () ? "primary80MHz" : "secondary80MHz") << "}"; + os << "RU{" << ru.GetRuType () << "/" << ru.GetIndex () << "/" << (ru.GetPrimary80MHz () ? "primary80MHz" : "secondary80MHz"); + if (ru.IsPhyIndexSet ()) + { + os << "[" << ru.GetPhyIndex () << "]"; + } + os << "}"; return os; } diff --git a/src/wifi/model/he/he-ru.h b/src/wifi/model/he/he-ru.h index e83ea63dd..d853ae2b9 100644 --- a/src/wifi/model/he/he-ru.h +++ b/src/wifi/model/he/he-ru.h @@ -57,9 +57,12 @@ public: /** - * RU Specification. Stores the information carried by the RU Allocation - * subfield of the User Info field of Trigger frames. Note that primary80MHz - * must be true if ruType is RU_2x996_TONE. + * RU Specification. Stores the information carried by the RU Allocation subfield + * of the User Info field of Trigger frames (see 9.3.1.22.1 of 802.11ax D8.0). + * Note that primary80MHz must be true if ruType is RU_2x996_TONE. + * Internally, this class also stores the RU PHY index (ranging from 1 to the number + * of RUs of the given type in a channel of the considered width), so that this class + * contains all the information needed to locate the RU in a 160 MHz channel. */ class RuSpec { @@ -95,11 +98,35 @@ public: * \return true if the RU is in the primary 80 MHz channel and false otherwise */ bool GetPrimary80MHz (void) const; + /** + * Set the RU PHY index + * + * \param bw the width of the channel of which the RU is part (in MHz) + * \param p20Index the index of the primary20 channel + */ + void SetPhyIndex (uint16_t bw, uint8_t p20Index); + /** + * Return true if the RU PHY index has been set, false otherwise + * + * \return true if the RU PHY index has been set, false otherwise + */ + bool IsPhyIndexSet (void) const; + /** + * Get the RU PHY index + * + * \return the RU PHY index + */ + std::size_t GetPhyIndex (void) const; private: RuType m_ruType; //!< RU type - std::size_t m_index; //!< index (starting at 1) + std::size_t m_index; /**< RU index (starting at 1) as defined by Tables 27-7 + to 27-9 of 802.11ax D8.0 */ bool m_primary80MHz; //!< true if the RU is allocated in the primary 80MHz channel + std::size_t m_phyIndex; /**< the RU PHY index, which is used to indicate whether an + RU is located in the lower half or the higher half of + a 160MHz channel. For channel widths less than 160MHz, + the RU PHY index equals the RU index */ };