diff --git a/src/wifi/model/frame-exchange-manager.h b/src/wifi/model/frame-exchange-manager.h index 46079bf11..f2eef20b4 100644 --- a/src/wifi/model/frame-exchange-manager.h +++ b/src/wifi/model/frame-exchange-manager.h @@ -522,7 +522,7 @@ protected: * \param mpdu the MPDU that solicited a Normal Ack response * \param txVector the TXVECTOR used to transmit the frame soliciting the Normal Ack */ - void NormalAckTimeout (Ptr mpdu, const WifiTxVector& txVector); + virtual void NormalAckTimeout (Ptr mpdu, const WifiTxVector& txVector); /** * Called when the CTS timeout expires. diff --git a/src/wifi/model/he/he-frame-exchange-manager.cc b/src/wifi/model/he/he-frame-exchange-manager.cc index 645ea69e7..9d34fef02 100644 --- a/src/wifi/model/he/he-frame-exchange-manager.cc +++ b/src/wifi/model/he/he-frame-exchange-manager.cc @@ -621,6 +621,12 @@ HeFrameExchangeManager::SendPsduMap (void) auto hePhy = StaticCast (m_phy->GetPhyEntity (WIFI_MOD_CLASS_HE)); hePhy->SetTrigVector (m_trigVector, m_txTimer.GetDelayLeft ()); } + else if (timerType == WifiTxTimer::NOT_RUNNING + && m_txParams.m_txVector.IsUlMu ()) + { + // clear m_psduMap after sending QoS Null frames following a BSRP Trigger Frame + Simulator::Schedule (txDuration, &WifiPsduMap::clear, &m_psduMap); + } } void @@ -999,6 +1005,52 @@ HeFrameExchangeManager::BlockAckAfterTbPpduTimeout (Ptr psdu, const Wi m_psduMap.clear (); } +void +HeFrameExchangeManager::NormalAckTimeout (Ptr mpdu, const WifiTxVector& txVector) +{ + NS_LOG_FUNCTION (this << *mpdu << txVector); + + VhtFrameExchangeManager::NormalAckTimeout (mpdu, txVector); + + // If a Normal Ack is missed in response to a DL MU PPDU requiring acknowledgment + // in SU format, we have to set the Retry flag for all transmitted MPDUs that have + // not been acknowledged nor discarded and clear m_psduMap since the transmission failed. + for (auto& psdu : m_psduMap) + { + for (auto& mpdu : *PeekPointer (psdu.second)) + { + if (mpdu->IsQueued ()) + { + mpdu->GetHeader ().SetRetry (); + } + } + } + m_psduMap.clear (); +} + +void +HeFrameExchangeManager::BlockAckTimeout (Ptr psdu, const WifiTxVector& txVector) +{ + NS_LOG_FUNCTION (this << *psdu << txVector); + + VhtFrameExchangeManager::BlockAckTimeout (psdu, txVector); + + // If a Block Ack is missed in response to a DL MU PPDU requiring acknowledgment + // in SU format, we have to set the Retry flag for all transmitted MPDUs that have + // not been acknowledged nor discarded and clear m_psduMap since the transmission failed. + for (auto& psdu : m_psduMap) + { + for (auto& mpdu : *PeekPointer (psdu.second)) + { + if (mpdu->IsQueued ()) + { + mpdu->GetHeader ().SetRetry (); + } + } + } + m_psduMap.clear (); +} + WifiTxVector HeFrameExchangeManager::GetTrigVector (const CtrlTriggerHeader& trigger) const { @@ -1509,6 +1561,7 @@ HeFrameExchangeManager::ReceiveMpdu (Ptr mpdu, RxSignalInfo rx SnrTag tag; mpdu->GetPacket ()->PeekPacketTag (tag); ReceivedNormalAck (*it->second->begin (), m_txParams.m_txVector, txVector, rxSignalInfo, tag.Get ()); + m_psduMap.clear (); } // TODO the PHY should not pass us a non-TB PPDU if we are waiting for a // TB PPDU. However, processing the PHY header is done by the PHY entity @@ -1635,6 +1688,15 @@ HeFrameExchangeManager::ReceiveMpdu (Ptr mpdu, RxSignalInfo rx m_channelAccessManager->NotifyAckTimeoutResetNow (); m_psduMap.clear (); } + else if (hdr.IsBlockAck () && m_txTimer.IsRunning () + && m_txTimer.GetReason () == WifiTxTimer::WAIT_BLOCK_ACK) + { + // this BlockAck frame may have been sent in response to a DL MU PPDU with + // acknowledgment in SU format or one of the consequent BlockAckReq frames. + // We clear the PSDU map and let parent classes continue processing this frame. + m_psduMap.clear (); + VhtFrameExchangeManager::ReceiveMpdu (mpdu, rxSignalInfo, txVector, inAmpdu); + } else if (hdr.IsTrigger ()) { // Trigger Frames are only processed by STAs diff --git a/src/wifi/model/he/he-frame-exchange-manager.h b/src/wifi/model/he/he-frame-exchange-manager.h index c4695dfb8..c6be10e03 100644 --- a/src/wifi/model/he/he-frame-exchange-manager.h +++ b/src/wifi/model/he/he-frame-exchange-manager.h @@ -101,6 +101,8 @@ protected: Time GetTxDuration (uint32_t ppduPayloadSize, Mac48Address receiver, const WifiTxParameters& txParams) const override; bool SendMpduFromBaManager (Ptr edca, Time availableTime, bool initialFrame) override; + void NormalAckTimeout (Ptr mpdu, const WifiTxVector& txVector) override; + void BlockAckTimeout (Ptr psdu, const WifiTxVector& txVector) override; void CtsTimeout (Ptr rts, const WifiTxVector& txVector) override; /**