diff --git a/src/wifi/model/frame-exchange-manager.cc b/src/wifi/model/frame-exchange-manager.cc index d5dc64516..2f942b4c2 100644 --- a/src/wifi/model/frame-exchange-manager.cc +++ b/src/wifi/model/frame-exchange-manager.cc @@ -9,6 +9,7 @@ #include "frame-exchange-manager.h" #include "ap-wifi-mac.h" +#include "gcr-manager.h" #include "snr-tag.h" #include "sta-wifi-mac.h" #include "wifi-mac-queue.h" @@ -523,8 +524,18 @@ FrameExchangeManager::SendMpdu() if (m_txParams.m_acknowledgment->method == WifiAcknowledgment::NONE) { - if (!m_mpdu->GetHeader().IsQosData() || - m_mpdu->GetHeader().GetQosAckPolicy() == WifiMacHeader::NO_ACK) + const auto isGcr = m_mac->GetTypeOfStation() == AP && m_apMac->UseGcr(m_mpdu->GetHeader()); + if (isGcr && m_apMac->GetGcrManager()->KeepGroupcastQueued(m_mpdu)) + { + // keep the groupcast frame in the queue for future retransmission + Simulator::Schedule(txDuration + m_phy->GetSifs(), [=, this, mpdu = m_mpdu]() { + NS_LOG_DEBUG("Prepare groupcast MPDU for retry"); + mpdu->ResetInFlight(m_linkId); + mpdu->GetHeader().SetRetry(); + }); + } + else if (!m_mpdu->GetHeader().IsQosData() || + m_mpdu->GetHeader().GetQosAckPolicy() == WifiMacHeader::NO_ACK) { // No acknowledgment, hence dequeue the MPDU if it is stored in a queue DequeueMpdu(m_mpdu); diff --git a/src/wifi/model/ht/ht-frame-exchange-manager.cc b/src/wifi/model/ht/ht-frame-exchange-manager.cc index 7ec041a58..297c3cd24 100644 --- a/src/wifi/model/ht/ht-frame-exchange-manager.cc +++ b/src/wifi/model/ht/ht-frame-exchange-manager.cc @@ -943,10 +943,20 @@ HtFrameExchangeManager::ReleaseSequenceNumbers(Ptr psdu) const { NS_LOG_FUNCTION(this << *psdu); - auto tids = psdu->GetTids(); + const auto tids = psdu->GetTids(); + const auto isGcr = IsGcr(m_mac, psdu->GetHeader(0)); + auto agreementEstablished = + !tids.empty() /* no QoS data frame included */ && + (isGcr ? GetBaManager(*tids.begin()) + ->IsGcrAgreementEstablished( + psdu->GetHeader(0).GetAddr1(), + *tids.begin(), + m_apMac->GetGcrManager()->GetMemberStasForGroupAddress( + psdu->GetHeader(0).GetAddr1())) + : m_mac->GetBaAgreementEstablishedAsOriginator(psdu->GetAddr1(), *tids.begin()) + .has_value()); - if (tids.empty() || // no QoS data frames included - !m_mac->GetBaAgreementEstablishedAsOriginator(psdu->GetAddr1(), *tids.begin())) + if (!agreementEstablished) { QosFrameExchangeManager::ReleaseSequenceNumbers(psdu); return; @@ -963,7 +973,15 @@ HtFrameExchangeManager::ReleaseSequenceNumbers(Ptr psdu) const if (hdr.IsQosData()) { uint8_t tid = hdr.GetQosTid(); - NS_ASSERT(m_mac->GetBaAgreementEstablishedAsOriginator(hdr.GetAddr1(), tid)); + agreementEstablished = + isGcr ? GetBaManager(tid)->IsGcrAgreementEstablished( + psdu->GetHeader(0).GetAddr1(), + tid, + m_apMac->GetGcrManager()->GetMemberStasForGroupAddress( + psdu->GetHeader(0).GetAddr1())) + : m_mac->GetBaAgreementEstablishedAsOriginator(psdu->GetAddr1(), tid) + .has_value(); + NS_ASSERT(agreementEstablished); if (!hdr.IsRetry() && !(*mpduIt)->IsInFlight()) { diff --git a/src/wifi/model/wifi-remote-station-manager.cc b/src/wifi/model/wifi-remote-station-manager.cc index 965a2ae6f..14e6a10e0 100644 --- a/src/wifi/model/wifi-remote-station-manager.cc +++ b/src/wifi/model/wifi-remote-station-manager.cc @@ -1121,7 +1121,7 @@ WifiRemoteStationManager::GetMpdusToDropOnTxFailure(Ptr psdu) { NS_LOG_FUNCTION(this << *psdu); - auto* station = Lookup(psdu->GetHeader(0).GetAddr1()); + auto* station = Lookup(GetIndividuallyAddressedRecipient(m_wifiMac, psdu->GetHeader(0))); DoIncrementRetryCountOnTxFailure(station, psdu); return DoGetMpdusToDropOnTxFailure(station, psdu);