wifi: Fix channel width in reconstructed TXVECTOR when receiving a non-HT duplicate PPDU

This commit is contained in:
Sébastien Deronne
2023-07-26 22:03:23 +02:00
committed by Sébastien Deronne
parent 42472134c4
commit aa5958e034
10 changed files with 108 additions and 66 deletions

View File

@@ -464,8 +464,8 @@ HePhy::DoGetEvent(Ptr<const WifiPpdu> ppdu, RxPowerWattPerChannelBand& rxPowersW
const auto uidPreamblePair = std::make_pair(ppdu->GetUid(), ppdu->GetPreamble());
const auto& currentPreambleEvents = GetCurrentPreambleEvents();
const auto it = currentPreambleEvents.find(uidPreamblePair);
const auto isResponseToTrigger = (m_previouslyTxPpduUid == ppdu->GetUid());
if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU || isResponseToTrigger)
if (const auto isResponseToTrigger = (m_previouslyTxPpduUid == ppdu->GetUid());
ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU || isResponseToTrigger)
{
const auto& txVector = ppdu->GetTxVector();
const auto rxDuration =
@@ -486,34 +486,7 @@ HePhy::DoGetEvent(Ptr<const WifiPpdu> ppdu, RxPowerWattPerChannelBand& rxPowersW
NS_LOG_DEBUG("Received another response to a trigger frame " << ppdu->GetUid());
}
event = it->second;
if (Simulator::Now() - event->GetStartTime() > GetMaxDelayPpduSameUid(txVector))
{
// This HE TB PPDU arrived too late to be decoded properly. The HE TB PPDU
// is dropped and added as interference
event = CreateInterferenceEvent(ppdu, rxDuration, rxPowersW);
NS_LOG_DEBUG("Drop HE TB PPDU that arrived too late");
m_wifiPhy->NotifyRxDrop(GetAddressedPsduInPpdu(ppdu), PPDU_TOO_LATE);
}
else
{
// Update received power of the event associated to that UL MU transmission
UpdateInterferenceEvent(event, rxPowersW);
}
if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU && GetCurrentEvent() &&
(GetCurrentEvent()->GetPpdu()->GetUid() != ppdu->GetUid()))
{
NS_LOG_DEBUG("Drop packet because already receiving another HE TB PPDU");
m_wifiPhy->NotifyRxDrop(GetAddressedPsduInPpdu(ppdu), RXING);
}
else if (isResponseToTrigger && GetCurrentEvent() &&
(GetCurrentEvent()->GetPpdu()->GetUid() != ppdu->GetUid()))
{
NS_LOG_DEBUG(
"Drop packet because already receiving another response to a trigger frame");
m_wifiPhy->NotifyRxDrop(GetAddressedPsduInPpdu(ppdu), RXING);
}
HandleRxPpduWithSameContent(event, ppdu, rxPowersW);
return nullptr;
}
else
@@ -547,6 +520,28 @@ HePhy::DoGetEvent(Ptr<const WifiPpdu> ppdu, RxPowerWattPerChannelBand& rxPowersW
return event;
}
void
HePhy::HandleRxPpduWithSameContent(Ptr<Event> event,
Ptr<const WifiPpdu> ppdu,
RxPowerWattPerChannelBand& rxPower)
{
VhtPhy::HandleRxPpduWithSameContent(event, ppdu, rxPower);
if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU && GetCurrentEvent() &&
(GetCurrentEvent()->GetPpdu()->GetUid() != ppdu->GetUid()))
{
NS_LOG_DEBUG("Drop packet because already receiving another HE TB PPDU");
m_wifiPhy->NotifyRxDrop(GetAddressedPsduInPpdu(ppdu), RXING);
}
else if (const auto isResponseToTrigger = (m_previouslyTxPpduUid == ppdu->GetUid());
isResponseToTrigger && GetCurrentEvent() &&
(GetCurrentEvent()->GetPpdu()->GetUid() != ppdu->GetUid()))
{
NS_LOG_DEBUG("Drop packet because already receiving another response to a trigger frame");
m_wifiPhy->NotifyRxDrop(GetAddressedPsduInPpdu(ppdu), RXING);
}
}
Ptr<const WifiPsdu>
HePhy::GetAddressedPsduInPpdu(Ptr<const WifiPpdu> ppdu) const
{
@@ -1820,18 +1815,6 @@ HePhy::GetRxPpduFromTxPpdu(Ptr<const WifiPpdu> ppdu)
hePpdu->UpdateTxVectorForUlMu(m_trigVector);
return rxPpdu;
}
else if (auto txVector = ppdu->GetTxVector();
m_currentTxVector.has_value() &&
(m_previouslyTxPpduUid == ppdu->GetUid()) && // response to a trigger frame
(txVector.GetModulationClass() < WIFI_MOD_CLASS_HT)) // PPDU is a non-HT (duplicate)
{
auto triggerChannelWidth = m_currentTxVector->GetChannelWidth();
if (txVector.GetChannelWidth() != triggerChannelWidth)
{
txVector.SetChannelWidth(triggerChannelWidth);
ppdu->UpdateTxVector(txVector);
}
}
return VhtPhy::GetRxPpduFromTxPpdu(ppdu);
}

View File

@@ -493,6 +493,9 @@ class HePhy : public VhtPhy
uint32_t GetMaxPsduSize() const override;
WifiConstPsduMap GetWifiConstPsduMap(Ptr<const WifiPsdu> psdu,
const WifiTxVector& txVector) const override;
void HandleRxPpduWithSameContent(Ptr<Event> event,
Ptr<const WifiPpdu> ppdu,
RxPowerWattPerChannelBand& rxPower) override;
/**
* Process SIG-A, perform amendment-specific actions, and

View File

@@ -124,6 +124,12 @@ Event::UpdateRxPowerW(const RxPowerWattPerChannelBand& rxPower)
}
}
void
Event::UpdatePpdu(Ptr<const WifiPpdu> ppdu)
{
m_ppdu = ppdu;
}
std::ostream&
operator<<(std::ostream& os, const Event& event)
{

View File

@@ -100,6 +100,15 @@ class Event : public SimpleRefCount<Event>
* \param rxPower the received power (W) for all bands.
*/
void UpdateRxPowerW(const RxPowerWattPerChannelBand& rxPower);
/**
* Update the PPDU that initially generated the event.
* This is needed to have the PPDU holding the correct TXVECTOR
* upon reception of multiple signals carring the same content
* but over different channel width (typically non-HT duplicates).
*
* \param ppdu the new PPDU to use for this event.
*/
void UpdatePpdu(Ptr<const WifiPpdu> ppdu);
private:
Ptr<const WifiPpdu> m_ppdu; //!< PPDU

View File

@@ -684,6 +684,25 @@ OfdmPhy::GetCcaThreshold(const Ptr<const WifiPpdu> ppdu, WifiChannelListType cha
return PhyEntity::GetCcaThreshold(ppdu, channelType);
}
Ptr<const WifiPpdu>
OfdmPhy::GetRxPpduFromTxPpdu(Ptr<const WifiPpdu> ppdu)
{
const auto txWidth = ppdu->GetTxChannelWidth();
const auto& txVector = ppdu->GetTxVector();
// Update channel width in TXVECTOR for non-HT duplicate PPDUs.
if ((txVector.IsNonHtDuplicate() && (txWidth > m_wifiPhy->GetChannelWidth())))
{
// We also do a copy of the PPDU for non-HT duplicate PPDUs since other
// PHYs might set a different channel width in the reconstructed TXVECTOR.
auto rxPpdu = ppdu->Copy();
auto updatedTxVector = txVector;
updatedTxVector.SetChannelWidth(std::min(txWidth, m_wifiPhy->GetChannelWidth()));
rxPpdu->UpdateTxVector(updatedTxVector);
return rxPpdu;
}
return PhyEntity::GetRxPpduFromTxPpdu(ppdu);
}
} // namespace ns3
namespace

View File

@@ -89,6 +89,7 @@ class OfdmPhy : public PhyEntity
Time ppduDuration) override;
double GetCcaThreshold(const Ptr<const WifiPpdu> ppdu,
WifiChannelListType channelType) const override;
Ptr<const WifiPpdu> GetRxPpduFromTxPpdu(Ptr<const WifiPpdu> ppdu) override;
/**
* Initialize all OFDM modes (for all variants).

View File

@@ -787,8 +787,7 @@ PhyEntity::GetReceptionStatus(Ptr<const WifiPsdu> psdu,
Time mpduDuration)
{
NS_LOG_FUNCTION(this << *psdu << *event << staId << relativeMpduStart << mpduDuration);
const auto& channelWidthAndBand =
GetChannelWidthAndBand(event->GetPpdu()->GetTxVector(), staId);
const auto channelWidthAndBand = GetChannelWidthAndBand(event->GetPpdu()->GetTxVector(), staId);
SnrPer snrPer = m_wifiPhy->m_interference->CalculatePayloadSnrPer(
event,
channelWidthAndBand.first,
@@ -859,21 +858,7 @@ PhyEntity::DoGetEvent(Ptr<const WifiPpdu> ppdu, RxPowerWattPerChannelBand& rxPow
// received another signal with the same content
NS_LOG_DEBUG("Received another PPDU for UID " << ppdu->GetUid());
const auto foundEvent = it->second;
const auto maxDelay =
m_wifiPhy->GetPhyEntityForPpdu(ppdu)->GetMaxDelayPpduSameUid(ppdu->GetTxVector());
if (Simulator::Now() - foundEvent->GetStartTime() > maxDelay)
{
// This PPDU arrived too late to be decoded properly. The PPDU is dropped and added as
// interference
CreateInterferenceEvent(ppdu, ppdu->GetTxDuration(), rxPowersW);
NS_LOG_DEBUG("Drop PPDU that arrived too late");
m_wifiPhy->NotifyRxDrop(GetAddressedPsduInPpdu(ppdu), PPDU_TOO_LATE);
}
else
{
// Update received power of the event associated to that transmission
UpdateInterferenceEvent(foundEvent, rxPowersW);
}
HandleRxPpduWithSameContent(foundEvent, ppdu, rxPowersW);
return nullptr;
}
@@ -892,9 +877,35 @@ PhyEntity::CreateInterferenceEvent(Ptr<const WifiPpdu> ppdu,
}
void
PhyEntity::UpdateInterferenceEvent(Ptr<Event> event, const RxPowerWattPerChannelBand& rxPower)
PhyEntity::HandleRxPpduWithSameContent(Ptr<Event> event,
Ptr<const WifiPpdu> ppdu,
RxPowerWattPerChannelBand& rxPower)
{
if (const auto maxDelay =
m_wifiPhy->GetPhyEntityForPpdu(ppdu)->GetMaxDelayPpduSameUid(ppdu->GetTxVector());
Simulator::Now() - event->GetStartTime() > maxDelay)
{
// This PPDU arrived too late to be decoded properly. The PPDU is dropped and added as
// interference
event = CreateInterferenceEvent(ppdu, ppdu->GetTxDuration(), rxPower);
NS_LOG_DEBUG("Drop PPDU that arrived too late");
m_wifiPhy->NotifyRxDrop(GetAddressedPsduInPpdu(ppdu), PPDU_TOO_LATE);
return;
}
// Update received power and TXVECTOR of the event associated to that transmission upon
// reception of a signal adding up constructively (in case of a UL MU PPDU or non-HT duplicate
// PPDU)
m_wifiPhy->m_interference->UpdateEvent(event, rxPower);
const auto& txVector = ppdu->GetTxVector();
const auto& eventTxVector = event->GetPpdu()->GetTxVector();
auto updatedTxVector{eventTxVector};
updatedTxVector.SetChannelWidth(
std::max(eventTxVector.GetChannelWidth(), txVector.GetChannelWidth()));
if (updatedTxVector.GetChannelWidth() != eventTxVector.GetChannelWidth())
{
event->UpdatePpdu(ppdu);
}
}
void

View File

@@ -846,13 +846,22 @@ class PhyEntity : public SimpleRefCount<PhyEntity>
RxPowerWattPerChannelBand& rxPower,
bool isStartHePortionRxing = false);
/**
* Update an event in WifiPhy's InterferenceHelper class.
* Wrapper used by child classes.
* Handle reception of a PPDU that carries the same content of another PPDU.
* This is typically called upon reception of preambles of HE MU PPDUs or reception
* of non-HT duplicate control frames that carries the exact same content sent from different
* STAs. If the delay between the PPDU and the first PPDU carrying the same content is small
* enough, PPDU can be decoded and its power is added constructively, and the TXVECTOR is
* updated accordingly. Otherwise, a new interference event is created and PPDU is dropped by
* the PHY.
*
* \param event the event to be updated
* \param rxPower the received power (W) per band to be added to the current event
* \param event the event of the ongoing reception
* \param ppdu the newly received PPDU (UL MU or non-HT duplicate)
* \param rxPower the received power (W) per band of the newly received PPDU
*/
void UpdateInterferenceEvent(Ptr<Event> event, const RxPowerWattPerChannelBand& rxPower);
virtual void HandleRxPpduWithSameContent(Ptr<Event> event,
Ptr<const WifiPpdu> ppdu,
RxPowerWattPerChannelBand& rxPower);
/**
* Notify WifiPhy's InterferenceHelper of the end of the reception,
* clear maps and end of MPDU event, and eventually reset WifiPhy.

View File

@@ -405,7 +405,7 @@ SpectrumWifiPhy::StartRx(Ptr<SpectrumSignalParameters> rxParams,
// Do no further processing if signal is too weak
// Current implementation assumes constant RX power over the PPDU duration
// Compare received TX power per MHz to normalized RX sensitivity
const auto& ppdu = GetRxPpduFromTxPpdu(wifiRxParams->ppdu);
const auto ppdu = GetRxPpduFromTxPpdu(wifiRxParams->ppdu);
if (totalRxPowerW < DbmToW(GetRxSensitivity()) * (ppdu->GetTxChannelWidth() / 20.0))
{
NS_LOG_INFO("Received signal too weak to process: " << WToDbm(totalRxPowerW) << " dBm");

View File

@@ -89,6 +89,7 @@ WifiPpdu::GetTxVector() const
m_txVector = DoGetTxVector();
m_txVector->SetTxPowerLevel(m_txPowerLevel);
m_txVector->SetNTx(m_txAntennas);
m_txVector->SetChannelWidth(m_txChannelWidth);
}
return m_txVector.value();
}