diff --git a/src/wifi/model/he/he-phy.cc b/src/wifi/model/he/he-phy.cc index 35476c44b..688996297 100644 --- a/src/wifi/model/he/he-phy.cc +++ b/src/wifi/model/he/he-phy.cc @@ -464,8 +464,8 @@ HePhy::DoGetEvent(Ptr 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 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 ppdu, RxPowerWattPerChannelBand& rxPowersW return event; } +void +HePhy::HandleRxPpduWithSameContent(Ptr event, + Ptr 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 HePhy::GetAddressedPsduInPpdu(Ptr ppdu) const { @@ -1820,18 +1815,6 @@ HePhy::GetRxPpduFromTxPpdu(Ptr 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); } diff --git a/src/wifi/model/he/he-phy.h b/src/wifi/model/he/he-phy.h index a3ee418d7..fe70fbecb 100644 --- a/src/wifi/model/he/he-phy.h +++ b/src/wifi/model/he/he-phy.h @@ -493,6 +493,9 @@ class HePhy : public VhtPhy uint32_t GetMaxPsduSize() const override; WifiConstPsduMap GetWifiConstPsduMap(Ptr psdu, const WifiTxVector& txVector) const override; + void HandleRxPpduWithSameContent(Ptr event, + Ptr ppdu, + RxPowerWattPerChannelBand& rxPower) override; /** * Process SIG-A, perform amendment-specific actions, and diff --git a/src/wifi/model/interference-helper.cc b/src/wifi/model/interference-helper.cc index 89fc2670f..7d75435ce 100644 --- a/src/wifi/model/interference-helper.cc +++ b/src/wifi/model/interference-helper.cc @@ -124,6 +124,12 @@ Event::UpdateRxPowerW(const RxPowerWattPerChannelBand& rxPower) } } +void +Event::UpdatePpdu(Ptr ppdu) +{ + m_ppdu = ppdu; +} + std::ostream& operator<<(std::ostream& os, const Event& event) { diff --git a/src/wifi/model/interference-helper.h b/src/wifi/model/interference-helper.h index f1ee01296..f14cf36ee 100644 --- a/src/wifi/model/interference-helper.h +++ b/src/wifi/model/interference-helper.h @@ -100,6 +100,15 @@ class Event : public SimpleRefCount * \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 ppdu); private: Ptr m_ppdu; //!< PPDU diff --git a/src/wifi/model/non-ht/ofdm-phy.cc b/src/wifi/model/non-ht/ofdm-phy.cc index cbe33bf9a..8fd7d48cc 100644 --- a/src/wifi/model/non-ht/ofdm-phy.cc +++ b/src/wifi/model/non-ht/ofdm-phy.cc @@ -684,6 +684,25 @@ OfdmPhy::GetCcaThreshold(const Ptr ppdu, WifiChannelListType cha return PhyEntity::GetCcaThreshold(ppdu, channelType); } +Ptr +OfdmPhy::GetRxPpduFromTxPpdu(Ptr 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 diff --git a/src/wifi/model/non-ht/ofdm-phy.h b/src/wifi/model/non-ht/ofdm-phy.h index 5fdc32c09..a1b556fa3 100644 --- a/src/wifi/model/non-ht/ofdm-phy.h +++ b/src/wifi/model/non-ht/ofdm-phy.h @@ -89,6 +89,7 @@ class OfdmPhy : public PhyEntity Time ppduDuration) override; double GetCcaThreshold(const Ptr ppdu, WifiChannelListType channelType) const override; + Ptr GetRxPpduFromTxPpdu(Ptr ppdu) override; /** * Initialize all OFDM modes (for all variants). diff --git a/src/wifi/model/phy-entity.cc b/src/wifi/model/phy-entity.cc index 7f404cc2c..23b668168 100644 --- a/src/wifi/model/phy-entity.cc +++ b/src/wifi/model/phy-entity.cc @@ -787,8 +787,7 @@ PhyEntity::GetReceptionStatus(Ptr 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 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 ppdu, } void -PhyEntity::UpdateInterferenceEvent(Ptr event, const RxPowerWattPerChannelBand& rxPower) +PhyEntity::HandleRxPpduWithSameContent(Ptr event, + Ptr 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 diff --git a/src/wifi/model/phy-entity.h b/src/wifi/model/phy-entity.h index 593958453..114cdc2ab 100644 --- a/src/wifi/model/phy-entity.h +++ b/src/wifi/model/phy-entity.h @@ -846,13 +846,22 @@ class PhyEntity : public SimpleRefCount 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, const RxPowerWattPerChannelBand& rxPower); + virtual void HandleRxPpduWithSameContent(Ptr event, + Ptr ppdu, + RxPowerWattPerChannelBand& rxPower); + /** * Notify WifiPhy's InterferenceHelper of the end of the reception, * clear maps and end of MPDU event, and eventually reset WifiPhy. diff --git a/src/wifi/model/spectrum-wifi-phy.cc b/src/wifi/model/spectrum-wifi-phy.cc index 16e58b34c..1f2439777 100644 --- a/src/wifi/model/spectrum-wifi-phy.cc +++ b/src/wifi/model/spectrum-wifi-phy.cc @@ -405,7 +405,7 @@ SpectrumWifiPhy::StartRx(Ptr 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"); diff --git a/src/wifi/model/wifi-ppdu.cc b/src/wifi/model/wifi-ppdu.cc index b68a6c37c..f29d1a3a2 100644 --- a/src/wifi/model/wifi-ppdu.cc +++ b/src/wifi/model/wifi-ppdu.cc @@ -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(); }