diff --git a/src/wifi/model/block-ack-manager.cc b/src/wifi/model/block-ack-manager.cc index b60daead9..98e00c7ce 100644 --- a/src/wifi/model/block-ack-manager.cc +++ b/src/wifi/model/block-ack-manager.cc @@ -62,14 +62,50 @@ BlockAckManager::DoDispose() m_queue = nullptr; } -BlockAckManager::OriginatorAgreementOptConstRef -BlockAckManager::GetAgreementAsOriginator(const Mac48Address& recipient, uint8_t tid) const +BlockAckManager::OriginatorAgreementsI +BlockAckManager::GetOriginatorBaAgreement(const Mac48Address& recipient, + uint8_t tid, + std::optional gcrGroupAddr) { - if (auto it = m_originatorAgreements.find({recipient, tid}); it != m_originatorAgreements.end()) + auto [first, last] = m_originatorAgreements.equal_range({recipient, tid}); + for (auto it = first; it != last; ++it) + { + [[maybe_unused]] const auto& [baAgreement, packetQueue] = it->second; + if (baAgreement.GetGcrGroupAddress() == gcrGroupAddr) + { + return it; + } + } + return m_originatorAgreements.end(); +} + +BlockAckManager::OriginatorAgreementsCI +BlockAckManager::GetOriginatorBaAgreement(const Mac48Address& recipient, + uint8_t tid, + std::optional gcrGroupAddr) const +{ + const auto [first, last] = m_originatorAgreements.equal_range({recipient, tid}); + for (auto it = first; it != last; ++it) + { + [[maybe_unused]] const auto& [baAgreement, packetQueue] = it->second; + if (baAgreement.GetGcrGroupAddress() == gcrGroupAddr) + { + return it; + } + } + return m_originatorAgreements.cend(); +} + +BlockAckManager::OriginatorAgreementOptConstRef +BlockAckManager::GetAgreementAsOriginator(const Mac48Address& recipient, + uint8_t tid, + std::optional gcrGroupAddr) const +{ + if (const auto it = GetOriginatorBaAgreement(recipient, tid, gcrGroupAddr); + it != m_originatorAgreements.cend()) { return std::cref(it->second.first); } - return std::nullopt; } @@ -112,17 +148,35 @@ BlockAckManager::CreateOriginatorAgreement(const MgtAddBaRequestHeader& reqHdr, agreement.SetGcrGroupAddress(*gcrGroupAddr); } agreement.SetState(OriginatorBlockAckAgreement::PENDING); + m_originatorAgreementState(Simulator::Now(), recipient, tid, OriginatorBlockAckAgreement::PENDING); - if (auto existingAgreement = GetAgreementAsOriginator(recipient, tid)) + + if (auto it = GetOriginatorBaAgreement(recipient, tid, reqHdr.GetGcrGroupAddress()); + it != m_originatorAgreements.end()) { - NS_ASSERT_MSG(existingAgreement->get().IsReset(), - "Existing agreement must be in RESET state"); + NS_ASSERT_MSG(it->second.first.IsReset(), "Existing agreement must be in RESET state"); + it->second = std::make_pair(std::move(agreement), PacketQueue{}); } - m_originatorAgreements.insert_or_assign({recipient, tid}, - std::make_pair(std::move(agreement), PacketQueue{})); + else + { + m_originatorAgreements.emplace(std::make_pair(recipient, tid), + std::make_pair(std::move(agreement), PacketQueue{})); + } + + const auto [first, last] = m_originatorAgreements.equal_range({recipient, tid}); + NS_ASSERT_MSG(std::count_if(first, + last, + [&reqHdr](const auto& elem) { + return elem.second.first.GetGcrGroupAddress() == + reqHdr.GetGcrGroupAddress(); + }) == 1, + "There exists more than one " + << (reqHdr.GetGcrGroupAddress().has_value() ? "GCR " : " ") + << "Block Ack agreement for recipient " << recipient << " and tid " << +tid); + m_blockPackets(recipient, tid); } @@ -130,8 +184,7 @@ void BlockAckManager::DestroyOriginatorAgreement(const Mac48Address& recipient, uint8_t tid) { NS_LOG_FUNCTION(this << recipient << tid); - auto it = m_originatorAgreements.find({recipient, tid}); - if (it != m_originatorAgreements.end()) + if (auto it = GetOriginatorBaAgreement(recipient, tid); it != m_originatorAgreements.end()) { m_originatorAgreements.erase(it); } @@ -143,9 +196,9 @@ BlockAckManager::UpdateOriginatorAgreement(const MgtAddBaResponseHeader& respHdr uint16_t startingSeq) { NS_LOG_FUNCTION(this << respHdr << recipient << startingSeq); - uint8_t tid = respHdr.GetTid(); - auto it = m_originatorAgreements.find({recipient, tid}); - if (it != m_originatorAgreements.end()) + const auto tid = respHdr.GetTid(); + if (auto it = GetOriginatorBaAgreement(recipient, tid, respHdr.GetGcrGroupAddress()); + it != m_originatorAgreements.end()) { OriginatorBlockAckAgreement& agreement = it->second.first; agreement.SetBufferSize(respHdr.GetBufferSize()); @@ -240,10 +293,10 @@ BlockAckManager::StorePacket(Ptr mpdu) NS_LOG_FUNCTION(this << *mpdu); NS_ASSERT(mpdu->GetHeader().IsQosData()); - uint8_t tid = mpdu->GetHeader().GetQosTid(); - Mac48Address recipient = mpdu->GetHeader().GetAddr1(); + const auto tid = mpdu->GetHeader().GetQosTid(); + const auto recipient = mpdu->GetHeader().GetAddr1(); - auto agreementIt = m_originatorAgreements.find({recipient, tid}); + auto agreementIt = GetOriginatorBaAgreement(recipient, tid); NS_ASSERT(agreementIt != m_originatorAgreements.end()); uint16_t mpduDist = @@ -284,12 +337,8 @@ BlockAckManager::StorePacket(Ptr mpdu) uint32_t BlockAckManager::GetNBufferedPackets(const Mac48Address& recipient, uint8_t tid) const { - auto it = m_originatorAgreements.find({recipient, tid}); - if (it == m_originatorAgreements.end()) - { - return 0; - } - return it->second.second.size(); + const auto it = GetOriginatorBaAgreement(recipient, tid); + return (it != m_originatorAgreements.cend()) ? it->second.second.size() : 0; } void @@ -370,10 +419,10 @@ BlockAckManager::NotifyGotAck(uint8_t linkId, Ptr mpdu) NS_LOG_FUNCTION(this << linkId << *mpdu); NS_ASSERT(mpdu->GetHeader().IsQosData()); - Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1(); - uint8_t tid = mpdu->GetHeader().GetQosTid(); + const auto recipient = mpdu->GetOriginal()->GetHeader().GetAddr1(); + const auto tid = mpdu->GetHeader().GetQosTid(); - auto it = m_originatorAgreements.find({recipient, tid}); + auto it = GetOriginatorBaAgreement(recipient, tid); NS_ASSERT(it != m_originatorAgreements.end()); NS_ASSERT(it->second.first.IsEstablished()); @@ -401,10 +450,10 @@ BlockAckManager::NotifyMissedAck(uint8_t linkId, Ptr mpdu) NS_LOG_FUNCTION(this << linkId << *mpdu); NS_ASSERT(mpdu->GetHeader().IsQosData()); - Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1(); - uint8_t tid = mpdu->GetHeader().GetQosTid(); + const auto recipient = mpdu->GetOriginal()->GetHeader().GetAddr1(); + const auto tid = mpdu->GetHeader().GetQosTid(); - auto it = m_originatorAgreements.find({recipient, tid}); + auto it = GetOriginatorBaAgreement(recipient, tid); NS_ASSERT(it != m_originatorAgreements.end()); NS_ASSERT(it->second.first.IsEstablished()); @@ -441,7 +490,7 @@ BlockAckManager::NotifyGotBlockAck(uint8_t linkId, tid = *tids.begin(); } - auto it = m_originatorAgreements.find({recipient, tid}); + auto it = GetOriginatorBaAgreement(recipient, tid); if (it == m_originatorAgreements.end() || !it->second.first.IsEstablished()) { return {0, 0}; @@ -518,13 +567,13 @@ BlockAckManager::NotifyMissedBlockAck(uint8_t linkId, const Mac48Address& recipi { NS_LOG_FUNCTION(this << linkId << recipient << tid); - auto it = m_originatorAgreements.find({recipient, tid}); + auto it = GetOriginatorBaAgreement(recipient, tid); if (it == m_originatorAgreements.end() || !it->second.first.IsEstablished()) { return; } - Time now = Simulator::Now(); + const auto now = Simulator::Now(); // remove all packets from the queue of outstanding packets (they will be // re-inserted if retransmitted) @@ -558,17 +607,17 @@ BlockAckManager::NotifyDiscardedMpdu(Ptr mpdu) return; } - Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1(); - uint8_t tid = mpdu->GetHeader().GetQosTid(); - auto it = m_originatorAgreements.find({recipient, tid}); + const auto recipient = mpdu->GetOriginal()->GetHeader().GetAddr1(); + const auto tid = mpdu->GetHeader().GetQosTid(); + auto it = GetOriginatorBaAgreement(recipient, tid); if (it == m_originatorAgreements.end() || !it->second.first.IsEstablished()) { NS_LOG_DEBUG("No established Block Ack agreement"); return; } - uint16_t currStartingSeq = it->second.first.GetStartingSequence(); - if (QosUtilsIsOldPacket(currStartingSeq, mpdu->GetHeader().GetSequenceNumber())) + if (const auto currStartingSeq = it->second.first.GetStartingSequence(); + QosUtilsIsOldPacket(currStartingSeq, mpdu->GetHeader().GetSequenceNumber())) { NS_LOG_DEBUG("Discarded an old frame"); return; @@ -647,7 +696,7 @@ BlockAckManager::NotifyGotMpdu(Ptr mpdu) CtrlBAckRequestHeader BlockAckManager::GetBlockAckReqHeader(const Mac48Address& recipient, uint8_t tid) const { - auto it = m_originatorAgreements.find({recipient, tid}); + auto it = GetOriginatorBaAgreement(recipient, tid); NS_ASSERT(it != m_originatorAgreements.end()); CtrlBAckRequestHeader reqHdr; reqHdr.SetType((*it).second.first.GetBlockAckReqType()); @@ -725,7 +774,7 @@ void BlockAckManager::NotifyOriginatorAgreementRejected(const Mac48Address& recipient, uint8_t tid) { NS_LOG_FUNCTION(this << recipient << tid); - auto it = m_originatorAgreements.find({recipient, tid}); + auto it = GetOriginatorBaAgreement(recipient, tid); NS_ASSERT(it != m_originatorAgreements.end()); if (!it->second.first.IsRejected()) { @@ -742,7 +791,7 @@ void BlockAckManager::NotifyOriginatorAgreementNoReply(const Mac48Address& recipient, uint8_t tid) { NS_LOG_FUNCTION(this << recipient << tid); - auto it = m_originatorAgreements.find({recipient, tid}); + auto it = GetOriginatorBaAgreement(recipient, tid); NS_ASSERT(it != m_originatorAgreements.end()); if (!it->second.first.IsNoReply()) { @@ -759,7 +808,7 @@ void BlockAckManager::NotifyOriginatorAgreementReset(const Mac48Address& recipient, uint8_t tid) { NS_LOG_FUNCTION(this << recipient << tid); - auto it = m_originatorAgreements.find({recipient, tid}); + auto it = GetOriginatorBaAgreement(recipient, tid); NS_ASSERT(it != m_originatorAgreements.end()); if (!it->second.first.IsReset()) { @@ -781,7 +830,7 @@ BlockAckManager::SetQueue(const Ptr queue) bool BlockAckManager::NeedBarRetransmission(uint8_t tid, const Mac48Address& recipient) { - auto it = m_originatorAgreements.find({recipient, tid}); + auto it = GetOriginatorBaAgreement(recipient, tid); if (it == m_originatorAgreements.end() || !it->second.first.IsEstablished()) { // If the inactivity timer has expired, QosTxop::SendDelbaFrame has been called and @@ -789,7 +838,7 @@ BlockAckManager::NeedBarRetransmission(uint8_t tid, const Mac48Address& recipien return false; } - Time now = Simulator::Now(); + const auto now = Simulator::Now(); // A BAR needs to be retransmitted if there is at least a non-expired in flight MPDU for (auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();) @@ -849,25 +898,15 @@ BlockAckManager::SetDroppedOldMpduCallback(DroppedOldMpdu callback) uint16_t BlockAckManager::GetRecipientBufferSize(const Mac48Address& recipient, uint8_t tid) const { - uint16_t size = 0; - auto it = m_originatorAgreements.find({recipient, tid}); - if (it != m_originatorAgreements.end()) - { - size = it->second.first.GetBufferSize(); - } - return size; + const auto it = GetOriginatorBaAgreement(recipient, tid); + return (it != m_originatorAgreements.cend()) ? it->second.first.GetBufferSize() : 0; } uint16_t BlockAckManager::GetOriginatorStartingSequence(const Mac48Address& recipient, uint8_t tid) const { - uint16_t seqNum = 0; - auto it = m_originatorAgreements.find({recipient, tid}); - if (it != m_originatorAgreements.end()) - { - seqNum = it->second.first.GetStartingSequence(); - } - return seqNum; + const auto it = GetOriginatorBaAgreement(recipient, tid); + return (it != m_originatorAgreements.cend()) ? it->second.first.GetStartingSequence() : 0; } } // namespace ns3 diff --git a/src/wifi/model/block-ack-manager.h b/src/wifi/model/block-ack-manager.h index 5de6628b1..579bf9908 100644 --- a/src/wifi/model/block-ack-manager.h +++ b/src/wifi/model/block-ack-manager.h @@ -74,13 +74,17 @@ class BlockAckManager : public Object /** * @param recipient MAC address of the recipient * @param tid Traffic ID + * @param gcrGroupAddr the GCR Group Address (only if it is a GCR Block Ack agreement) * * @return a const reference to the block ack agreement with the given recipient, if it exists * * Check if we are the originator of an existing block ack agreement with the given recipient. */ - OriginatorAgreementOptConstRef GetAgreementAsOriginator(const Mac48Address& recipient, - uint8_t tid) const; + OriginatorAgreementOptConstRef GetAgreementAsOriginator( + const Mac48Address& recipient, + uint8_t tid, + std::optional gcrGroupAddr = std::nullopt) const; + /** * @param originator MAC address of the originator * @param tid Traffic ID @@ -440,13 +444,39 @@ class BlockAckManager : public Object /// AgreementKey-indexed map of originator block ack agreements using OriginatorAgreements = - std::map>; + std::multimap>; /// typedef for an iterator for Agreements using OriginatorAgreementsI = OriginatorAgreements::iterator; + /// typedef for a const iterator for Agreements + using OriginatorAgreementsCI = OriginatorAgreements::const_iterator; /// AgreementKey-indexed map of recipient block ack agreements using RecipientAgreements = std::map; + /** + * @param recipient MAC address of the recipient + * @param tid Traffic ID + * @param gcrGroupAddr the GCR Group Address (only if it is a GCR Block Ack agreement) + * + * @return an iterator to the block ack agreement + */ + OriginatorAgreementsI GetOriginatorBaAgreement( + const Mac48Address& recipient, + uint8_t tid, + std::optional gcrGroupAddr = std::nullopt); + + /** + * @param recipient MAC address of the recipient + * @param tid Traffic ID + * @param gcrGroupAddr the GCR Group Address (only if it is a GCR Block Ack agreement) + * + * @return a const iterator to the block ack agreement + */ + OriginatorAgreementsCI GetOriginatorBaAgreement( + const Mac48Address& recipient, + uint8_t tid, + std::optional gcrGroupAddr = std::nullopt) const; + /** * Handle the given in flight MPDU based on its given status. If the status is * ACKNOWLEDGED, the MPDU is removed from both the EDCA queue and the queue of diff --git a/src/wifi/model/ht/ht-frame-exchange-manager.cc b/src/wifi/model/ht/ht-frame-exchange-manager.cc index aeb992458..d96749172 100644 --- a/src/wifi/model/ht/ht-frame-exchange-manager.cc +++ b/src/wifi/model/ht/ht-frame-exchange-manager.cc @@ -806,14 +806,21 @@ HtFrameExchangeManager::NotifyPacketDiscarded(Ptr mpdu) if (actionHdr.GetCategory() == WifiActionHeader::BLOCK_ACK && actionHdr.GetAction().blockAck == WifiActionHeader::BLOCK_ACK_ADDBA_REQUEST) { - uint8_t tid = GetTid(mpdu->GetPacket(), mpdu->GetHeader()); + const auto tid = GetTid(mpdu->GetPacket(), mpdu->GetHeader()); auto recipient = mpdu->GetHeader().GetAddr1(); // if the recipient is an MLD, use its MLD address if (auto mldAddr = GetWifiRemoteStationManager()->GetMldAddress(recipient)) { recipient = *mldAddr; } - if (auto agreement = GetBaManager(tid)->GetAgreementAsOriginator(recipient, tid); + auto p = mpdu->GetPacket()->Copy(); + p->RemoveHeader(actionHdr); + MgtAddBaRequestHeader addBa; + p->PeekHeader(addBa); + if (auto agreement = + GetBaManager(tid)->GetAgreementAsOriginator(recipient, + tid, + addBa.GetGcrGroupAddress()); agreement && agreement->get().IsPending()) { NS_LOG_DEBUG("No ACK after ADDBA request");