wifi: add function to reconstruct per user information in TXVECTOR for DL OFDMA

This commit is contained in:
Sébastien Deronne
2022-10-27 20:29:09 +02:00
committed by Sebastien Deronne
parent 27c99b5c5d
commit 0d7bd988e0
5 changed files with 96 additions and 2 deletions

View File

@@ -97,9 +97,15 @@ EhtPpdu::SetTxVectorFromPhyHeaders(WifiTxVector& txVector,
txVector.SetLength(lSig.GetLength());
txVector.SetAggregation(m_psdus.size() > 1 || m_psdus.begin()->second->IsAggregate());
txVector.SetEhtPpduType(m_ehtPpduType); // FIXME: PPDU type should be read from U-SIG
for (const auto& muUserInfo : m_muUserInfos)
if (txVector.IsDlMu())
{
txVector.SetHeMuUserInfo(muUserInfo.first, muUserInfo.second);
auto copyTxVector = txVector;
for (const auto& muUserInfo : m_muUserInfos)
{
txVector.SetHeMuUserInfo(muUserInfo.first, muUserInfo.second);
}
SetHeMuUserInfos(copyTxVector, heSig);
NS_ASSERT(txVector.GetHeMuUserInfoMap() == copyTxVector.GetHeMuUserInfoMap());
}
if (ns3::IsDlMu(m_preamble))
{

View File

@@ -223,10 +223,13 @@ HePpdu::SetTxVectorFromPhyHeaders(WifiTxVector& txVector,
}
if (IsDlMu())
{
auto copyTxVector = txVector;
for (const auto& muUserInfo : m_muUserInfos)
{
txVector.SetHeMuUserInfo(muUserInfo.first, muUserInfo.second);
}
SetHeMuUserInfos(copyTxVector, heSig);
NS_ASSERT(txVector.GetHeMuUserInfoMap() == copyTxVector.GetHeMuUserInfoMap());
}
if (txVector.IsDlMu())
{
@@ -241,6 +244,71 @@ HePpdu::SetTxVectorFromPhyHeaders(WifiTxVector& txVector,
}
}
void
HePpdu::SetHeMuUserInfos(WifiTxVector& txVector, const HeSigHeader& heSig) const
{
WifiTxVector::HeMuUserInfoMap userInfos{};
const auto contentChannels = heSig.GetHeSigBContentChannels();
const auto ruAllocation = heSig.GetRuAllocation();
auto contentChannelIndex = 0;
for (const auto& contentChannel : contentChannels)
{
auto numRusLeft = 0;
auto ruAllocIndex = contentChannelIndex;
for (const auto& userInfo : contentChannel)
{
auto ruSpecs = HeRu::GetRuSpecs(ruAllocation.at(ruAllocIndex));
if (ruSpecs.empty())
{
continue;
}
if (numRusLeft == 0)
{
numRusLeft = ruSpecs.size();
}
auto ruIndex = (ruSpecs.size() - numRusLeft);
auto ruSpec = ruSpecs.at(ruIndex);
auto ruType = ruSpec.GetRuType();
if ((ruAllocation.size() == 8) && (ruType == HeRu::RU_996_TONE) &&
(std::all_of(
contentChannel.cbegin(),
contentChannel.cend(),
[&userInfo](const auto& item) { return userInfo.staId == item.staId; })))
{
NS_ASSERT(txVector.GetChannelWidth() == 160);
ruType = HeRu::RU_2x996_TONE;
}
const auto ruBw = HeRu::GetBandwidth(ruType);
auto primary80 = ruAllocIndex < 4;
auto num20MhzSubchannelsInRu = (ruBw < 20) ? 1 : (ruBw / 20);
auto numRuAllocsInContentChannel = std::max(1, num20MhzSubchannelsInRu / 2);
auto ruIndexOffset = (ruBw < 20) ? (ruSpecs.size() * ruAllocIndex)
: (ruAllocIndex / num20MhzSubchannelsInRu);
if (!primary80)
{
ruIndexOffset -= HeRu::GetRusOfType(80, ruType).size();
}
if (!txVector.IsAllocated(userInfo.staId))
{
txVector.SetHeMuUserInfo(userInfo.staId,
{{ruType, ruSpec.GetIndex() + ruIndexOffset, primary80},
userInfo.mcs,
userInfo.nss});
}
if (ruType == HeRu::RU_2x996_TONE)
{
return;
}
numRusLeft--;
if (numRusLeft == 0)
{
ruAllocIndex += (2 * numRuAllocsInContentChannel);
}
}
contentChannelIndex++;
}
}
Time
HePpdu::GetTxDuration() const
{

View File

@@ -370,6 +370,14 @@ class HePpdu : public OfdmPpdu
const LSigHeader& lSig,
const HeSigHeader& heSig) const;
/**
* Reconstruct HeMuUserInfoMap from HE-SIG-B header.
*
* \param txVector the TXVECTOR to set its HeMuUserInfoMap
* \param heSig the HE-SIG-B to use to reconstruct HeMuUserInfoMap
*/
void SetHeMuUserInfos(WifiTxVector& txVector, const HeSigHeader& heSig) const;
#ifndef NS3_BUILD_PROFILE_DEBUG
HeSigHeader m_heSig; //!< the HE-SIG PHY header
#endif

View File

@@ -482,6 +482,12 @@ WifiTxVector::IsUlMu() const
return ns3::IsUlMu(m_preamble);
}
bool
WifiTxVector::IsAllocated(uint16_t staId) const
{
return m_muUserInfos.count(staId) > 0;
}
HeRu::RuSpec
WifiTxVector::GetRu(uint16_t staId) const
{

View File

@@ -378,6 +378,12 @@ class WifiTxVector
* transmission
*/
bool IsUlMu() const;
/**
* Check if STA ID is allocated
* \param staId STA ID
* \return true if allocated, false otherwise
*/
bool IsAllocated(uint16_t staId) const;
/**
* Get the RU specification for the STA-ID.
* This is applicable only for MU.