wifi: HE TB TXVECTOR parameters should be obtained from the TRIGVECTOR instead of HE-SIG-A header
This commit is contained in:
committed by
Tom Henderson
parent
30db47be6f
commit
3f5b18b922
@@ -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() &&
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user