diff --git a/src/wifi/model/mpdu-aggregator.cc b/src/wifi/model/mpdu-aggregator.cc index 4ccd5d844..f530a03df 100644 --- a/src/wifi/model/mpdu-aggregator.cc +++ b/src/wifi/model/mpdu-aggregator.cc @@ -229,8 +229,16 @@ MpduAggregator::GetNextAmpdu(Ptr mpdu, auto qosTxop = m_mac->GetQosTxop(tid); NS_ASSERT(qosTxop); + const auto isGcr = IsGcr(m_mac, header); + const auto bufferSize = qosTxop->GetBaBufferSize(origRecipient, tid, isGcr); + const auto startSeq = qosTxop->GetBaStartingSequence(origRecipient, tid, isGcr); + // Have to make sure that the block ack agreement is established and A-MPDU is enabled - if (m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid) && + auto apMac = DynamicCast(m_mac); + const auto agreementEstablished = + isGcr ? apMac->IsGcrBaAgreementEstablishedWithAllMembers(header.GetAddr1(), tid) + : m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid).has_value(); + if (agreementEstablished && GetMaxAmpduSize(recipient, tid, txParams.m_txVector.GetModulationClass()) > 0) { /* here is performed MPDU aggregation */ @@ -238,6 +246,23 @@ MpduAggregator::GetNextAmpdu(Ptr mpdu, while (nextMpdu) { + const auto isGcrUr = isGcr && (apMac->GetGcrManager()->GetRetransmissionPolicy() == + GroupAddressRetransmissionPolicy::GCR_UNSOLICITED_RETRY); + if (isGcrUr && header.IsRetry() && !nextMpdu->GetHeader().IsRetry()) + { + // if this is a retransmitted A-MPDU transmitted via GCR-UR, do not add new MPDU + break; + } + if (isGcr && + apMac->GetGcrManager()->GetRetransmissionPolicyFor(header) != + apMac->GetGcrManager()->GetRetransmissionPolicyFor(nextMpdu->GetHeader())) + { + // if an MPDU has been previously transmitted using No-Ack/No-Retry, + // do not add a new MPDU that still needs to be transmitted using No-Ack/No-Retry, + // unless No-Ack/No-Retry is the only selected retransmission policy + break; + } + // if we are here, nextMpdu can be aggregated to the A-MPDU. NS_LOG_DEBUG("Adding packet with sequence number " << nextMpdu->GetHeader().GetSequenceNumber() @@ -254,9 +279,8 @@ MpduAggregator::GetNextAmpdu(Ptr mpdu, if (peekedMpdu) { // PeekNextMpdu() does not return an MPDU that is beyond the transmit window - NS_ASSERT(IsInWindow(peekedMpdu->GetHeader().GetSequenceNumber(), - qosTxop->GetBaStartingSequence(origRecipient, tid), - qosTxop->GetBaBufferSize(origRecipient, tid))); + NS_ASSERT( + IsInWindow(peekedMpdu->GetHeader().GetSequenceNumber(), startSeq, bufferSize)); peekedMpdu = m_htFem->CreateAliasIfNeeded(peekedMpdu); // get the next MPDU to aggregate, provided that the constraints on size diff --git a/src/wifi/model/qos-txop.cc b/src/wifi/model/qos-txop.cc index 6dbe9ab27..8e83bed79 100644 --- a/src/wifi/model/qos-txop.cc +++ b/src/wifi/model/qos-txop.cc @@ -11,6 +11,7 @@ #include "qos-txop.h" +#include "ap-wifi-mac.h" #include "channel-access-manager.h" #include "ctrl-headers.h" #include "mac-tx-middle.h" @@ -436,13 +437,25 @@ QosTxop::PeekNextMpdu(uint8_t linkId, uint8_t tid, Mac48Address recipient, PtrGetHeader().IsQosData() && - !m_mac->GetBaAgreementEstablishedAsOriginator(item->GetHeader().GetAddr1(), - item->GetHeader().GetQosTid())) + if (item->GetHeader().IsQosData()) { - NS_LOG_DEBUG("No BA agreement and an MPDU is already in-flight"); - return nullptr; + auto apMac = DynamicCast(m_mac); + const auto isGcr = IsGcr(m_mac, item->GetHeader()); + const auto agreementEstablished = + isGcr + ? apMac->IsGcrBaAgreementEstablishedWithAllMembers( + item->GetHeader().GetAddr1(), + item->GetHeader().GetQosTid()) + : m_mac + ->GetBaAgreementEstablishedAsOriginator(item->GetHeader().GetAddr1(), + item->GetHeader().GetQosTid()) + .has_value(); + // if no BA agreement, we cannot have multiple MPDUs in-flight + if (!agreementEstablished) + { + NS_LOG_DEBUG("No BA agreement and an MPDU is already in-flight"); + return nullptr; + } } NS_LOG_DEBUG("Skipping in flight MPDU: " << *item); @@ -467,21 +480,24 @@ QosTxop::PeekNextMpdu(uint8_t linkId, uint8_t tid, Mac48Address recipient, PtrGetHeader(); + auto& hdr = item->GetHeader(); // peek the next sequence number and check if it is within the transmit window // in case of QoS data frame - uint16_t sequence = item->HasSeqNoAssigned() ? hdr.GetSequenceNumber() - : m_txMiddle->PeekNextSequenceNumberFor(&hdr); + const auto sequence = item->HasSeqNoAssigned() ? hdr.GetSequenceNumber() + : m_txMiddle->PeekNextSequenceNumberFor(&hdr); if (hdr.IsQosData()) { - Mac48Address recipient = hdr.GetAddr1(); - uint8_t tid = hdr.GetQosTid(); - - if (m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid) && - !IsInWindow(sequence, - GetBaStartingSequence(recipient, tid), - GetBaBufferSize(recipient, tid))) + const auto recipient = hdr.GetAddr1(); + const auto tid = hdr.GetQosTid(); + const auto isGcr = IsGcr(m_mac, hdr); + const auto bufferSize = GetBaBufferSize(recipient, tid, isGcr); + const auto startSeq = GetBaStartingSequence(recipient, tid, isGcr); + auto apMac = DynamicCast(m_mac); + const auto agreementEstablished = + isGcr ? apMac->IsGcrBaAgreementEstablishedWithAllMembers(recipient, tid) + : m_mac->GetBaAgreementEstablishedAsOriginator(recipient, tid).has_value(); + if (agreementEstablished && !IsInWindow(sequence, startSeq, bufferSize)) { NS_LOG_DEBUG("Packet beyond the end of the current transmit window"); return nullptr; diff --git a/src/wifi/model/wifi-default-ack-manager.cc b/src/wifi/model/wifi-default-ack-manager.cc index e4e51deff..dd03e4fcf 100644 --- a/src/wifi/model/wifi-default-ack-manager.cc +++ b/src/wifi/model/wifi-default-ack-manager.cc @@ -292,8 +292,8 @@ WifiDefaultAckManager::TryAddMpdu(Ptr mpdu, const WifiTxParamete if (receiver.IsGroup()) { - NS_ABORT_MSG_IF(!txParams.LastAddedIsFirstMpdu(receiver), - "Unicast frames only can be aggregated"); + NS_ABORT_MSG_IF(!IsGcr(m_mac, hdr) && !txParams.LastAddedIsFirstMpdu(receiver), + "Unicast frames only can be aggregated if GCR is not used"); auto acknowledgment = std::make_unique(); if (hdr.IsQosData()) {