wifi: HE TB TXVECTOR parameters should be obtained from the TRIGVECTOR instead of HE-SIG-A header

This commit is contained in:
Sébastien Deronne
2023-03-01 21:13:14 +01:00
committed by Tom Henderson
parent 30db47be6f
commit 3f5b18b922
7 changed files with 133 additions and 45 deletions

View File

@@ -77,7 +77,8 @@ const PhyEntity::PpduFormats HePhy::m_hePpduFormats { // Ignoring PE (Packet Ext
HePhy::HePhy(bool buildModeList /* = true */)
: VhtPhy(false), // don't add VHT modes to list
m_trigVectorExpirationTime(Seconds(0)),
m_trigVector(std::nullopt),
m_trigVectorExpirationTime(std::nullopt),
m_currentTxVector(std::nullopt),
m_rxHeTbPpdus(0),
m_lastPer20MHzDurations()
@@ -323,9 +324,13 @@ HePhy::SetTrigVector(const WifiTxVector& trigVector, Time validity)
NS_LOG_FUNCTION(this << trigVector << validity);
NS_ASSERT_MSG(trigVector.GetGuardInterval() > 800,
"Invalid guard interval " << trigVector.GetGuardInterval());
if (auto mac = m_wifiPhy->GetDevice()->GetMac(); mac && mac->GetTypeOfStation() != AP)
{
return;
}
m_trigVector = trigVector;
m_trigVectorExpirationTime = Simulator::Now() + validity;
NS_LOG_FUNCTION(this << m_trigVector << m_trigVectorExpirationTime.As(Time::US));
NS_LOG_FUNCTION(this << m_trigVector.value() << m_trigVectorExpirationTime->As(Time::US));
}
Ptr<WifiPpdu>
@@ -351,7 +356,7 @@ HePhy::StartReceivePreamble(Ptr<const WifiPpdu> ppdu,
const auto& txVector = ppdu->GetTxVector();
auto hePpdu = DynamicCast<const HePpdu>(ppdu);
NS_ASSERT(hePpdu);
HePpdu::TxPsdFlag psdFlag = hePpdu->GetTxPsdFlag();
const auto psdFlag = hePpdu->GetTxPsdFlag();
if (psdFlag == HePpdu::PSD_HE_PORTION)
{
NS_ASSERT(txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE);
@@ -652,18 +657,21 @@ HePhy::ProcessSigA(Ptr<Event> event, PhyFieldRxStatus status)
// When SIG-A is decoded, we know the type of frame being received. If we stored a
// valid TRIGVECTOR and we are not receiving a TB PPDU, we drop the frame.
if (m_trigVectorExpirationTime >= Simulator::Now() && !txVector.IsUlMu())
Ptr<const WifiPpdu> ppdu = event->GetPpdu();
if (m_trigVectorExpirationTime.has_value() &&
(m_trigVectorExpirationTime.value() >= Simulator::Now()) &&
(ppdu->GetType() != WIFI_PPDU_TYPE_UL_MU))
{
NS_LOG_DEBUG("Expected an HE TB PPDU, receiving a " << txVector.GetPreambleType());
return PhyFieldRxStatus(false, FILTERED, DROP);
}
Ptr<const WifiPpdu> ppdu = event->GetPpdu();
if (txVector.IsUlMu())
if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
{
NS_ASSERT(txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE);
// check that the stored TRIGVECTOR is still valid
if (m_trigVectorExpirationTime < Simulator::Now())
if (!m_trigVectorExpirationTime.has_value() ||
(m_trigVectorExpirationTime < Simulator::Now()))
{
NS_LOG_DEBUG("No valid TRIGVECTOR, the PHY was not expecting a TB PPDU");
return PhyFieldRxStatus(false, FILTERED, DROP);
@@ -673,28 +681,32 @@ HePhy::ProcessSigA(Ptr<Event> event, PhyFieldRxStatus status)
// OBSS, as BSS Colors are not guaranteed to be different for all APs in
// range (an example is when BSS Color is 0). We can detect this situation
// by comparing the TRIGVECTOR with the TXVECTOR of the TB PPDU being received
if (m_trigVector.GetChannelWidth() != txVector.GetChannelWidth())
NS_ABORT_IF(!m_trigVector.has_value());
if (m_trigVector->GetChannelWidth() != txVector.GetChannelWidth())
{
NS_LOG_DEBUG("Received channel width different than in TRIGVECTOR");
return PhyFieldRxStatus(false, FILTERED, DROP);
}
if (m_trigVector.GetLength() != txVector.GetLength())
if (m_trigVector->GetLength() != txVector.GetLength())
{
NS_LOG_DEBUG("Received UL Length (" << txVector.GetLength()
<< ") different than in TRIGVECTOR ("
<< m_trigVector.GetLength() << ")");
<< m_trigVector->GetLength() << ")");
return PhyFieldRxStatus(false, FILTERED, DROP);
}
uint16_t staId = ppdu->GetStaId();
if (m_trigVector.GetHeMuUserInfoMap().find(staId) ==
m_trigVector.GetHeMuUserInfoMap().end() ||
m_trigVector.GetHeMuUserInfo(staId) != txVector.GetHeMuUserInfo(staId))
if (m_trigVector->GetHeMuUserInfoMap().find(staId) ==
m_trigVector->GetHeMuUserInfoMap().end())
{
NS_LOG_DEBUG(
"User Info map of TB PPDU being received differs from that of TRIGVECTOR");
NS_LOG_DEBUG("TB PPDU received from un unexpected STA ID");
return PhyFieldRxStatus(false, FILTERED, DROP);
}
NS_ASSERT(txVector.GetGuardInterval() == m_trigVector->GetGuardInterval());
NS_ASSERT(txVector.GetMode(staId) == m_trigVector->GetMode(staId));
NS_ASSERT(txVector.GetNss(staId) == m_trigVector->GetNss(staId));
NS_ASSERT(txVector.GetHeMuUserInfo(staId) == m_trigVector->GetHeMuUserInfo(staId));
m_currentMuPpduUid =
ppdu->GetUid(); // to be able to correctly schedule start of OFDMA payload
}
@@ -767,6 +779,11 @@ HePhy::ProcessSigB(Ptr<Event> event, PhyFieldRxStatus status)
bool
HePhy::IsConfigSupported(Ptr<const WifiPpdu> ppdu) const
{
if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
{
return true; // evaluated in ProcessSigA
}
const WifiTxVector& txVector = ppdu->GetTxVector();
uint16_t staId = GetStaId(ppdu);
WifiMode txMode = txVector.GetMode(staId);
@@ -943,6 +960,7 @@ HePhy::DoEndReceivePayload(Ptr<const WifiPpdu> ppdu)
void
HePhy::StartReceiveOfdmaPayload(Ptr<Event> event)
{
NS_LOG_FUNCTION(this << event);
Ptr<const WifiPpdu> ppdu = event->GetPpdu();
const RxPowerWattPerChannelBand& rxPowersW = event->GetRxPowerWPerBand();
// The total RX power corresponds to the maximum over all the bands.
@@ -1820,13 +1838,25 @@ HePhy::CanStartRx(Ptr<const WifiPpdu> ppdu, uint16_t txChannelWidth) const
Ptr<const WifiPpdu>
HePhy::GetRxPpduFromTxPpdu(Ptr<const WifiPpdu> ppdu)
{
// We only copy if the AP that is expecting a HE TB PPDU, since the content
// of the TXVECTOR is reconstructed from the TRIGVECTOR, hence the other RX
// PHYs should not have this information.
if ((ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU) &&
(Simulator::Now() <= m_trigVectorExpirationTime))
if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
{
return ppdu->Copy();
Ptr<const WifiPpdu> rxPpdu;
if ((m_trigVectorExpirationTime.has_value()) &&
(Simulator::Now() <= m_trigVectorExpirationTime.value()))
{
// We only copy if the AP that is expecting a HE TB PPDU, since the content
// of the TXVECTOR is reconstructed from the TRIGVECTOR, hence the other RX
// PHYs should not have this information.
rxPpdu = ppdu->Copy();
}
else
{
rxPpdu = ppdu;
}
auto hePpdu = DynamicCast<const HePpdu>(rxPpdu);
NS_ASSERT(hePpdu);
hePpdu->UpdateTxVectorForUlMu(m_trigVector);
return rxPpdu;
}
else if (auto txVector = ppdu->GetTxVector();
m_currentTxVector.has_value() &&

View File

@@ -523,11 +523,11 @@ class HePhy : public VhtPhy
m_beginOfdmaPayloadRxEvents; //!< the beginning of the OFDMA payload reception events
//!< (indexed by STA-ID)
EndOfHeSigACallback m_endOfHeSigACallback; //!< end of HE-SIG-A callback
WifiTxVector m_trigVector; //!< the TRIGVECTOR
Time m_trigVectorExpirationTime; //!< expiration time of the TRIGVECTOR
std::optional<WifiTxVector> m_currentTxVector; //!< If the STA is an AP STA, this holds the
//!< TXVECTOR of the PPDU that has been sent
EndOfHeSigACallback m_endOfHeSigACallback; //!< end of HE-SIG-A callback
std::optional<WifiTxVector> m_trigVector; //!< the TRIGVECTOR
std::optional<Time> m_trigVectorExpirationTime; //!< expiration time of the TRIGVECTOR
std::optional<WifiTxVector> m_currentTxVector; //!< If the STA is an AP STA, this holds the
//!< TXVECTOR of the PPDU that has been sent
private:
void BuildModeList() override;

View File

@@ -155,7 +155,10 @@ HePpdu::SetHeSigHeader(HeSigHeader& heSig, const WifiTxVector& txVector) const
}
heSig.SetBssColor(txVector.GetBssColor());
heSig.SetChannelWidth(txVector.GetChannelWidth());
heSig.SetGuardIntervalAndLtfSize(txVector.GetGuardInterval(), 2 /*NLTF currently unused*/);
if (!txVector.IsUlMu())
{
heSig.SetGuardIntervalAndLtfSize(txVector.GetGuardInterval(), 2 /*NLTF currently unused*/);
}
}
WifiTxVector
@@ -192,16 +195,25 @@ HePpdu::SetTxVectorFromPhyHeaders(WifiTxVector& txVector,
const LSigHeader& lSig,
const HeSigHeader& heSig) const
{
txVector.SetMode(HePhy::GetHeMcs(heSig.GetMcs()));
txVector.SetChannelWidth(heSig.GetChannelWidth());
txVector.SetNss(heSig.GetNStreams());
txVector.SetGuardInterval(heSig.GetGuardInterval());
txVector.SetBssColor(heSig.GetBssColor());
txVector.SetLength(lSig.GetLength());
txVector.SetAggregation(m_psdus.size() > 1 || m_psdus.begin()->second->IsAggregate());
for (const auto& muUserInfo : m_muUserInfos)
if (!IsMu())
{
txVector.SetHeMuUserInfo(muUserInfo.first, muUserInfo.second);
txVector.SetMode(HePhy::GetHeMcs(heSig.GetMcs()));
txVector.SetNss(heSig.GetNStreams());
}
if (!IsUlMu())
{
txVector.SetGuardInterval(heSig.GetGuardInterval());
}
if (IsDlMu())
{
for (const auto& muUserInfo : m_muUserInfos)
{
txVector.SetHeMuUserInfo(muUserInfo.first, muUserInfo.second);
}
}
if (txVector.IsDlMu())
{
@@ -336,8 +348,8 @@ HePpdu::GetStaId() const
uint16_t
HePpdu::GetTransmissionChannelWidth() const
{
WifiTxVector txVector = GetTxVector();
if (txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB && GetStaId() != SU_STA_ID)
const WifiTxVector& txVector = GetTxVector();
if (txVector.IsUlMu() && GetStaId() != SU_STA_ID)
{
TxPsdFlag flag = GetTxPsdFlag();
uint16_t ruWidth = HeRu::GetBandwidth(txVector.GetRu(GetStaId()).GetRuType());
@@ -365,6 +377,42 @@ HePpdu::SetTxPsdFlag(TxPsdFlag flag) const
m_txPsdFlag = flag;
}
void
HePpdu::UpdateTxVectorForUlMu(const std::optional<WifiTxVector>& trigVector) const
{
if (trigVector.has_value())
{
NS_LOG_FUNCTION(this << trigVector.value());
}
else
{
NS_LOG_FUNCTION(this);
}
if (!m_txVector.has_value())
{
m_txVector = GetTxVector();
}
NS_ASSERT(GetModulation() >= WIFI_MOD_CLASS_HE);
NS_ASSERT(GetType() == WIFI_PPDU_TYPE_UL_MU);
// HE TB PPDU reception needs information from the TRIGVECTOR to be able to receive the PPDU
const auto staId = GetStaId();
if (trigVector.has_value() && trigVector->IsUlMu() &&
(trigVector->GetHeMuUserInfoMap().count(staId) > 0))
{
// These information are not carried in HE-SIG-A for a HE TB PPDU,
// but they are carried in the Trigger frame soliciting the HE TB PPDU
m_txVector->SetGuardInterval(trigVector->GetGuardInterval());
m_txVector->SetHeMuUserInfo(staId, trigVector->GetHeMuUserInfo(staId));
}
else
{
// Set dummy user info, PPDU will be dropped later after decoding PHY headers.
m_txVector->SetHeMuUserInfo(
staId,
{{HeRu::GetRuType(m_txVector->GetChannelWidth()), 1, true}, 0, 1});
}
}
bool
HePpdu::IsAllocated(uint16_t staId) const
{

View File

@@ -224,6 +224,15 @@ class HePpdu : public OfdmPpdu
*/
void SetTxPsdFlag(TxPsdFlag flag) const;
/**
* Update the TXVECTOR for HE TB PPDUs, since the information to decode HE TB PPDUs
* is not available from the PHY headers but it requires information from the TRIGVECTOR
* of the AP expecting these HE TB PPDUs.
*
* \param trigVector the TRIGVECTOR or std::nullopt if no TRIGVECTOR is available at the caller
*/
void UpdateTxVectorForUlMu(const std::optional<WifiTxVector>& trigVector) const;
/**
* Check if STA ID is in HE SIG-B Content Channel ID
* \param staId STA ID

View File

@@ -695,7 +695,8 @@ const Ptr<const PhyEntity>
WifiPhy::GetStaticPhyEntity(WifiModulationClass modulation)
{
const auto it = GetStaticPhyEntities().find(modulation);
NS_ABORT_MSG_IF(it == GetStaticPhyEntities().cend(), "Unimplemented Wi-Fi modulation class");
NS_ABORT_MSG_IF(it == GetStaticPhyEntities().cend(),
"Unimplemented Wi-Fi modulation class " << modulation);
return it->second;
}
@@ -1817,7 +1818,8 @@ WifiPhy::StartReceivePreamble(Ptr<const WifiPpdu> ppdu,
RxPowerWattPerChannelBand& rxPowersW,
Time rxDuration)
{
WifiModulationClass modulation = ppdu->GetTxVector().GetModulationClass();
NS_LOG_FUNCTION(this << ppdu << rxDuration);
WifiModulationClass modulation = ppdu->GetModulation();
auto it = m_phyEntities.find(modulation);
if (it != m_phyEntities.end())
{

View File

@@ -37,12 +37,12 @@ WifiPpdu::WifiPpdu(Ptr<const WifiPsdu> psdu,
m_modulation(txVector.IsValid() ? txVector.GetModulationClass() : WIFI_MOD_CLASS_UNKNOWN),
m_txCenterFreq(txCenterFreq),
m_uid(uid),
m_txVector(txVector),
#ifdef NS3_BUILD_PROFILE_DEBUG
m_phyHeaders(Create<Packet>()),
#endif
m_truncatedTx(false),
m_txPowerLevel(txVector.GetTxPowerLevel()),
m_txVector(txVector)
m_txPowerLevel(txVector.GetTxPowerLevel())
{
NS_LOG_FUNCTION(this << *psdu << txVector << txCenterFreq << uid);
m_psdus.insert(std::make_pair(SU_STA_ID, psdu));
@@ -57,13 +57,13 @@ WifiPpdu::WifiPpdu(const WifiConstPsduMap& psdus,
: WIFI_MOD_CLASS_UNKNOWN),
m_txCenterFreq(txCenterFreq),
m_uid(uid),
m_txVector(txVector),
#ifdef NS3_BUILD_PROFILE_DEBUG
m_phyHeaders(Create<Packet>()),
#endif
m_truncatedTx(false),
m_txPowerLevel(txVector.GetTxPowerLevel()),
m_txAntennas(txVector.GetNTx()),
m_txVector(txVector)
m_txAntennas(txVector.GetNTx())
{
NS_LOG_FUNCTION(this << psdus << txVector << txCenterFreq << uid);
m_psdus = psdus;

View File

@@ -203,6 +203,9 @@ class WifiPpdu : public SimpleRefCount<WifiPpdu>
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
mutable std::optional<WifiTxVector>
m_txVector; //!< the TXVECTOR at TX PHY or the reconstructed TXVECTOR at RX PHY (or
//!< std::nullopt if TXVECTOR has not been reconstructed yet)
#ifdef NS3_BUILD_PROFILE_DEBUG
Ptr<Packet> m_phyHeaders; //!< the PHY headers contained in this PPDU
@@ -221,11 +224,7 @@ class WifiPpdu : public SimpleRefCount<WifiPpdu>
uint8_t m_txPowerLevel; //!< the transmission power level (used only for TX and initializing the
//!< returned WifiTxVector)
uint8_t m_txAntennas; //!< the number of antennas used to transmit this PPDU
mutable std::optional<WifiTxVector>
m_txVector; //!< the TXVECTOR at TX PHY or the reconstructed TXVECTOR at RX PHY (or
//!< std::nullopt if TXVECTOR has not been reconstructed yet)
}; // class WifiPpdu
}; // class WifiPpdu
/**
* \brief Stream insertion operator.