diff --git a/src/wifi/model/he/he-ppdu.cc b/src/wifi/model/he/he-ppdu.cc index f228ca4dc..b4c30e325 100644 --- a/src/wifi/model/he/he-ppdu.cc +++ b/src/wifi/model/he/he-ppdu.cc @@ -136,7 +136,7 @@ HePpdu::SetHeSigHeader(const WifiTxVector& txVector) .m_giLtfSize = GetGuardIntervalAndNltfEncoding(txVector.GetGuardInterval(), 2 /*NLTF currently unused*/), .m_ruAllocation = txVector.GetRuAllocation(p20Index), - .m_contentChannels = txVector.GetContentChannels(p20Index), + .m_contentChannels = GetContentChannels(txVector, p20Index), .m_center26ToneRuIndication = (txVector.GetChannelWidth() >= 80) ? std::optional{txVector.GetCenter26ToneRuIndication()} @@ -493,6 +493,69 @@ HePpdu::GetNumRusPerHeSigBContentChannel(uint16_t channelWidth, const RuAllocati return chSize; } +HePpdu::HeSigBContentChannels +HePpdu::GetContentChannels(const WifiTxVector& txVector, uint8_t p20Index) +{ + HeSigBContentChannels contentChannels{{}}; + + const auto channelWidth = txVector.GetChannelWidth(); + if (channelWidth > 20) + { + contentChannels.emplace_back(); + } + + const auto& orderedRus = txVector.GetOrderedRus(p20Index); + for (const auto& [ru, staId] : orderedRus) + { + auto ruType = ru.GetRuType(); + auto ruIdx = ru.GetIndex(); + const auto& userInfo = txVector.GetHeMuUserInfo(staId); + NS_ASSERT(ru == userInfo.ru); + + if (ruType > HeRu::RU_242_TONE) + { + for (auto i = 0; i < ((ruType == HeRu::RU_2x996_TONE) ? 2 : 1); ++i) + { + contentChannels[0].push_back({staId, userInfo.nss, userInfo.mcs}); + contentChannels[1].push_back({staId, userInfo.nss, userInfo.mcs}); + } + continue; + } + + std::size_t numRus = (ruType >= HeRu::RU_242_TONE) + ? 1 + : HeRu::m_heRuSubcarrierGroups.at({20, ruType}).size(); + if (((ruIdx - 1) / numRus) % 2 == 0) + { + contentChannels.at(0).push_back({staId, userInfo.nss, userInfo.mcs}); + } + else + { + contentChannels.at(1).push_back({staId, userInfo.nss, userInfo.mcs}); + } + } + + // Add unassigned RUs + auto numNumRusPerHeSigBContentChannel = + GetNumRusPerHeSigBContentChannel(channelWidth, txVector.GetRuAllocation(p20Index)); + std::size_t contentChannelIndex = 1; + for (auto& contentChannel : contentChannels) + { + const auto totalUsersInContentChannel = (contentChannelIndex == 1) + ? numNumRusPerHeSigBContentChannel.first + : numNumRusPerHeSigBContentChannel.second; + NS_ASSERT(contentChannel.size() <= totalUsersInContentChannel); + std::size_t unallocatedRus = totalUsersInContentChannel - contentChannel.size(); + for (std::size_t i = 0; i < unallocatedRus; i++) + { + contentChannel.push_back({NO_USER_STA_ID, 0, 0}); + } + contentChannelIndex++; + } + + return contentChannels; +} + uint32_t HePpdu::GetSigBFieldSize(uint16_t channelWidth, const RuAllocation& ruAllocation) { diff --git a/src/wifi/model/he/he-ppdu.h b/src/wifi/model/he/he-ppdu.h index 7f4f207c8..f7913be5e 100644 --- a/src/wifi/model/he/he-ppdu.h +++ b/src/wifi/model/he/he-ppdu.h @@ -49,6 +49,17 @@ class WifiPsdu; class HePpdu : public OfdmPpdu { public: + /// User Specific Fields in HE-SIG-Bs. + struct HeSigBUserSpecificField + { + uint16_t staId : 11; ///< STA-ID + uint8_t nss : 4; ///< number of spatial streams + uint8_t mcs : 4; ///< MCS index + }; + + /// HE SIG-B Content Channels + using HeSigBContentChannels = std::vector>; + /** * HE-SIG PHY header for HE SU PPDUs (HE-SIG-A1/A2) */ @@ -189,6 +200,16 @@ class HePpdu : public OfdmPpdu uint16_t channelWidth, const RuAllocation& ruAllocation); + /** + * Get the HE SIG-B content channels for a given PPDU + * IEEE 802.11ax-2021 27.3.11.8.2 HE-SIG-B content channels + * + * \param txVector the TXVECTOR used for the PPDU + * \param p20Index the index of the primary20 channel + * \return HE-SIG-B content channels + */ + static HeSigBContentChannels GetContentChannels(const WifiTxVector& txVector, uint8_t p20Index); + /** * Get variable length HE SIG-B field size * \param channelWidth the channel width occupied by the PPDU (in MHz) diff --git a/src/wifi/model/wifi-tx-vector.cc b/src/wifi/model/wifi-tx-vector.cc index 1260bc29d..f90e67fb1 100644 --- a/src/wifi/model/wifi-tx-vector.cc +++ b/src/wifi/model/wifi-tx-vector.cc @@ -660,68 +660,6 @@ WifiTxVector::GetOrderedRus(uint8_t p20Index) const return orderedRus; } -HeSigBContentChannels -WifiTxVector::GetContentChannels(uint8_t p20Index) const -{ - HeSigBContentChannels contentChannels{{}}; - - if (m_channelWidth > 20) - { - contentChannels.emplace_back(); - } - - const auto& orderedRus = GetOrderedRus(p20Index); - for (const auto& [ru, staId] : orderedRus) - { - auto ruType = ru.GetRuType(); - auto ruIdx = ru.GetIndex(); - const auto& userInfo = GetHeMuUserInfo(staId); - NS_ASSERT(ru == userInfo.ru); - - if (ruType > HeRu::RU_242_TONE) - { - for (auto i = 0; i < ((ruType == HeRu::RU_2x996_TONE) ? 2 : 1); ++i) - { - contentChannels[0].push_back({staId, userInfo.nss, userInfo.mcs}); - contentChannels[1].push_back({staId, userInfo.nss, userInfo.mcs}); - } - continue; - } - - std::size_t numRus = (ruType >= HeRu::RU_242_TONE) - ? 1 - : HeRu::m_heRuSubcarrierGroups.at({20, ruType}).size(); - if (((ruIdx - 1) / numRus) % 2 == 0) - { - contentChannels.at(0).push_back({staId, userInfo.nss, userInfo.mcs}); - } - else - { - contentChannels.at(1).push_back({staId, userInfo.nss, userInfo.mcs}); - } - } - - // Add unassigned RUs - auto numNumRusPerHeSigBContentChannel = - HePpdu::GetNumRusPerHeSigBContentChannel(m_channelWidth, GetRuAllocation(p20Index)); - std::size_t contentChannelIndex = 1; - for (auto& contentChannel : contentChannels) - { - const auto totalUsersInContentChannel = (contentChannelIndex == 1) - ? numNumRusPerHeSigBContentChannel.first - : numNumRusPerHeSigBContentChannel.second; - NS_ASSERT(contentChannel.size() <= totalUsersInContentChannel); - std::size_t unallocatedRus = totalUsersInContentChannel - contentChannel.size(); - for (std::size_t i = 0; i < unallocatedRus; i++) - { - contentChannel.push_back({NO_USER_STA_ID, 0, 0}); - } - contentChannelIndex++; - } - - return contentChannels; -} - RuAllocation WifiTxVector::DeriveRuAllocation(uint8_t p20Index) const { diff --git a/src/wifi/model/wifi-tx-vector.h b/src/wifi/model/wifi-tx-vector.h index 4e54f9a5c..3265b0756 100644 --- a/src/wifi/model/wifi-tx-vector.h +++ b/src/wifi/model/wifi-tx-vector.h @@ -59,17 +59,6 @@ struct HeMuUserInfo bool operator!=(const HeMuUserInfo& other) const; }; -/// User Specific Fields in HE-SIG-Bs. -struct HeSigBUserSpecificField -{ - uint16_t staId : 11; ///< STA-ID - uint8_t nss : 4; ///< number of spatial streams - uint8_t mcs : 4; ///< MCS index -}; - -/// HE SIG-B Content Channels -using HeSigBContentChannels = std::vector>; - /// 8 bit RU_ALLOCATION per 20 MHz using RuAllocation = std::vector; @@ -488,14 +477,6 @@ class WifiTxVector */ const RuAllocation& GetRuAllocation(uint8_t p20Index) const; - /** - * Get the HE SIG-B content channels - * IEEE 802.11ax-2021 27.3.11.8.2 HE-SIG-B content channels - * \param p20Index the index of the primary20 channel - * \return HE-SIG-B content channels - */ - HeSigBContentChannels GetContentChannels(uint8_t p20Index) const; - /** * Set CENTER_26_TONE_RU field * \param center26ToneRuIndication the CENTER_26_TONE_RU field diff --git a/src/wifi/test/tx-duration-test.cc b/src/wifi/test/tx-duration-test.cc index df4f1d8b6..93d1faba0 100644 --- a/src/wifi/test/tx-duration-test.cc +++ b/src/wifi/test/tx-duration-test.cc @@ -1396,7 +1396,7 @@ HeSigBDurationTest::DoRun() const auto& numUsersPerCc = HePpdu::GetNumRusPerHeSigBContentChannel(txVector.GetChannelWidth(), txVector.GetRuAllocation(0)); - const auto contentChannels = txVector.GetContentChannels(0); + const auto contentChannels = HePpdu::GetContentChannels(txVector, 0); NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first, m_expectedNumUsersPerCc.first, "Incorrect number of users in HE-SIG-B content channel 1");