wifi: Fix channel width in reconstructed TXVECTOR when receiving a non-HT duplicate PPDU
This commit is contained in:
committed by
Sébastien Deronne
parent
42472134c4
commit
aa5958e034
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user