diff --git a/src/wifi/model/he/he-phy.cc b/src/wifi/model/he/he-phy.cc index 58accec8b..953c6fa73 100644 --- a/src/wifi/model/he/he-phy.cc +++ b/src/wifi/model/he/he-phy.cc @@ -677,48 +677,64 @@ HePhy::IsConfigSupported (Ptr ppdu) const return true; } -void +Time HePhy::DoStartReceivePayload (Ptr event) { NS_LOG_FUNCTION (this << *event); const WifiTxVector& txVector = event->GetTxVector (); Ptr ppdu = event->GetPpdu (); - if (txVector.IsUlMu ()) + if (!txVector.IsUlMu ()) { - NS_ASSERT (txVector.GetModulationClass () == WIFI_MOD_CLASS_HE); - bool isAp = (DynamicCast (m_wifiPhy->GetDevice ()->GetMac ()) != 0); - if (!isAp) + return PhyEntity::DoStartReceivePayload (event); + } + + NS_ASSERT (txVector.GetModulationClass () == WIFI_MOD_CLASS_HE); + // TX duration is determined by the Length field of TXVECTOR + Time payloadDuration = ConvertLSigLengthToHeTbPpduDuration (txVector.GetLength (), + txVector, + m_wifiPhy->GetPhyBand ()) + - CalculatePhyPreambleAndHeaderDuration (txVector); + // This method is called when we start receiving the first OFDMA payload. To + // compute the time to the reception end of the last TB PPDU, we need to add the + // offset of the last TB PPDU to the payload duration (same for all TB PPDUs) + Time maxOffset {0}; + for (const auto& beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) + { + maxOffset = Max (maxOffset, Simulator::GetDelayLeft (beginOfdmaPayloadRxEvent.second)); + } + Time timeToEndRx = payloadDuration + maxOffset; + + bool isAp = (DynamicCast (m_wifiPhy->GetDevice ()->GetMac ()) != 0); + if (!isAp) + { + NS_LOG_DEBUG ("Ignore HE TB PPDU payload received by STA but keep state in Rx"); + NotifyPayloadBegin (txVector, timeToEndRx); + m_endRxPayloadEvents.push_back (Simulator::Schedule (timeToEndRx, + &PhyEntity::ResetReceive, this, event)); + //Cancel all scheduled events for OFDMA payload reception + NS_ASSERT (!m_beginOfdmaPayloadRxEvents.empty () && m_beginOfdmaPayloadRxEvents.begin ()->second.IsRunning ()); + for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) { - NS_LOG_DEBUG ("Ignore HE TB PPDU payload received by STA but keep state in Rx"); - m_endRxPayloadEvents.push_back (Simulator::Schedule (ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector), - &PhyEntity::ResetReceive, this, event)); - //Cancel all scheduled events for OFDMA payload reception - NS_ASSERT (!m_beginOfdmaPayloadRxEvents.empty () && m_beginOfdmaPayloadRxEvents.begin ()->second.IsRunning ()); - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - beginOfdmaPayloadRxEvent.second.Cancel (); - } - m_beginOfdmaPayloadRxEvents.clear (); - } - else - { - NS_LOG_DEBUG ("Receiving PSDU in HE TB PPDU"); - uint16_t staId = GetStaId (ppdu); - m_signalNoiseMap.insert ({std::make_pair (ppdu->GetUid (), staId), SignalNoiseDbm ()}); - m_statusPerMpduMap.insert ({std::make_pair (ppdu->GetUid (), staId), std::vector ()}); - //for HE TB PPDUs, ScheduleEndOfMpdus and EndReceive are scheduled by StartReceiveOfdmaPayload - NS_ASSERT (isAp); - NS_ASSERT (!m_beginOfdmaPayloadRxEvents.empty ()); - for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) - { - NS_ASSERT (beginOfdmaPayloadRxEvent.second.IsRunning ()); - } + beginOfdmaPayloadRxEvent.second.Cancel (); } + m_beginOfdmaPayloadRxEvents.clear (); } else { - PhyEntity::DoStartReceivePayload (event); + NS_LOG_DEBUG ("Receiving PSDU in HE TB PPDU"); + uint16_t staId = GetStaId (ppdu); + m_signalNoiseMap.insert ({std::make_pair (ppdu->GetUid (), staId), SignalNoiseDbm ()}); + m_statusPerMpduMap.insert ({std::make_pair (ppdu->GetUid (), staId), std::vector ()}); + //for HE TB PPDUs, ScheduleEndOfMpdus and EndReceive are scheduled by StartReceiveOfdmaPayload + NS_ASSERT (isAp); + NS_ASSERT (!m_beginOfdmaPayloadRxEvents.empty ()); + for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents) + { + NS_ASSERT (beginOfdmaPayloadRxEvent.second.IsRunning ()); + } } + + return timeToEndRx; } void diff --git a/src/wifi/model/he/he-phy.h b/src/wifi/model/he/he-phy.h index 9588ae643..07c15375b 100644 --- a/src/wifi/model/he/he-phy.h +++ b/src/wifi/model/he/he-phy.h @@ -386,7 +386,7 @@ protected: PhyFieldRxStatus ProcessSigB (Ptr event, PhyFieldRxStatus status) override; Ptr DoGetEvent (Ptr ppdu, RxPowerWattPerChannelBand& rxPowersW) override; bool IsConfigSupported (Ptr ppdu) const override; - void DoStartReceivePayload (Ptr event) override; + Time DoStartReceivePayload (Ptr event) override; std::pair GetChannelWidthAndBand (const WifiTxVector& txVector, uint16_t staId) const override; void RxPayloadSucceeded (Ptr psdu, RxSignalInfo rxSignalInfo, const WifiTxVector& txVector, uint16_t staId, diff --git a/src/wifi/model/phy-entity.cc b/src/wifi/model/phy-entity.cc index 5f7f14959..32abad45b 100644 --- a/src/wifi/model/phy-entity.cc +++ b/src/wifi/model/phy-entity.cc @@ -529,17 +529,12 @@ PhyEntity::StartReceivePayload (Ptr event) { NS_LOG_FUNCTION (this << *event); NS_ASSERT (m_wifiPhy->m_endPhyRxEvent.IsExpired ()); - const WifiTxVector& txVector = event->GetTxVector (); - Time payloadDuration = event->GetPpdu ()->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector); - //TODO: Add method in WifiPhy to clear all other PHYs (since this one is starting Rx) + Time payloadDuration = DoStartReceivePayload (event); m_state->SwitchToRx (payloadDuration); - m_wifiPhy->m_phyRxPayloadBeginTrace (txVector, payloadDuration); //this callback (equivalent to PHY-RXSTART primitive) is triggered only if headers have been correctly decoded and that the mode within is supported - - DoStartReceivePayload (event); } -void +Time PhyEntity::DoStartReceivePayload (Ptr event) { NS_LOG_FUNCTION (this << *event); @@ -549,8 +544,12 @@ PhyEntity::DoStartReceivePayload (Ptr event) m_signalNoiseMap.insert ({std::make_pair (ppdu->GetUid (), staId), SignalNoiseDbm ()}); m_statusPerMpduMap.insert ({std::make_pair (ppdu->GetUid (), staId), std::vector ()}); ScheduleEndOfMpdus (event); - m_endRxPayloadEvents.push_back (Simulator::Schedule (ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (event->GetTxVector ()), + const WifiTxVector& txVector = event->GetTxVector (); + Time payloadDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector); + m_wifiPhy->m_phyRxPayloadBeginTrace (txVector, payloadDuration); //this callback (equivalent to PHY-RXSTART primitive) is triggered only if headers have been correctly decoded and that the mode within is supported + m_endRxPayloadEvents.push_back (Simulator::Schedule (payloadDuration, &PhyEntity::EndReceivePayload, this, event)); + return payloadDuration; } void diff --git a/src/wifi/model/phy-entity.h b/src/wifi/model/phy-entity.h index c3174ebaa..2008e635a 100644 --- a/src/wifi/model/phy-entity.h +++ b/src/wifi/model/phy-entity.h @@ -560,8 +560,9 @@ protected: * and perform amendment-specific actions. * * \param event the event holding incoming PPDU's information + * \return the payload duration */ - virtual void DoStartReceivePayload (Ptr event); + virtual Time DoStartReceivePayload (Ptr event); /** * Perform amendment-specific actions before resetting PHY at diff --git a/src/wifi/model/wifi-phy-state-helper.cc b/src/wifi/model/wifi-phy-state-helper.cc index b6a4fe2a6..d2f997ead 100644 --- a/src/wifi/model/wifi-phy-state-helper.cc +++ b/src/wifi/model/wifi-phy-state-helper.cc @@ -502,8 +502,7 @@ void WifiPhyStateHelper::SwitchFromRxEndOk (void) { NS_LOG_FUNCTION (this); - NS_ASSERT (Abs (m_endRx - Simulator::Now ()) < MicroSeconds (1)); //1us corresponds to the maximum propagation delay (delay spread) - //TODO: a better fix would be to call the function once all HE TB PPDUs are received + NS_ASSERT (m_endRx == Simulator::Now ()); NotifyRxEndOk (); DoSwitchFromRx (); } @@ -512,8 +511,7 @@ void WifiPhyStateHelper::SwitchFromRxEndError (void) { NS_LOG_FUNCTION (this); - NS_ASSERT (Abs (m_endRx - Simulator::Now ()) < MicroSeconds (1)); //1us corresponds to the maximum propagation delay (delay spread) - //TODO: a better fix would be to call the function once all HE TB PPDUs are received + NS_ASSERT (m_endRx == Simulator::Now ()); NotifyRxEndError (); DoSwitchFromRx (); }