From bc0a9b596989653bbf5c08289fe001def2bc560b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Fri, 17 Jan 2025 12:36:37 +0100 Subject: [PATCH] wifi: Use multimap for recipient block agreements --- src/wifi/model/block-ack-manager.cc | 92 +++++++++++++++---- src/wifi/model/block-ack-manager.h | 41 ++++++++- .../model/ht/ht-frame-exchange-manager.cc | 11 ++- 3 files changed, 115 insertions(+), 29 deletions(-) diff --git a/src/wifi/model/block-ack-manager.cc b/src/wifi/model/block-ack-manager.cc index 98e00c7ce..653cded71 100644 --- a/src/wifi/model/block-ack-manager.cc +++ b/src/wifi/model/block-ack-manager.cc @@ -96,6 +96,38 @@ BlockAckManager::GetOriginatorBaAgreement(const Mac48Address& recipient, return m_originatorAgreements.cend(); } +BlockAckManager::RecipientAgreementsI +BlockAckManager::GetRecipientBaAgreement(const Mac48Address& originator, + uint8_t tid, + std::optional gcrGroupAddr) +{ + auto [first, last] = m_recipientAgreements.equal_range({originator, tid}); + for (auto it = first; it != last; ++it) + { + if (it->second.GetGcrGroupAddress() == gcrGroupAddr) + { + return it; + } + } + return m_recipientAgreements.end(); +} + +BlockAckManager::RecipientAgreementsCI +BlockAckManager::GetRecipientBaAgreement(const Mac48Address& originator, + uint8_t tid, + std::optional gcrGroupAddr) const +{ + const auto [first, last] = m_recipientAgreements.equal_range({originator, tid}); + for (auto it = first; it != last; ++it) + { + if (it->second.GetGcrGroupAddress() == gcrGroupAddr) + { + return it; + } + } + return m_recipientAgreements.cend(); +} + BlockAckManager::OriginatorAgreementOptConstRef BlockAckManager::GetAgreementAsOriginator(const Mac48Address& recipient, uint8_t tid, @@ -110,13 +142,15 @@ BlockAckManager::GetAgreementAsOriginator(const Mac48Address& recipient, } BlockAckManager::RecipientAgreementOptConstRef -BlockAckManager::GetAgreementAsRecipient(const Mac48Address& originator, uint8_t tid) const +BlockAckManager::GetAgreementAsRecipient(const Mac48Address& originator, + uint8_t tid, + std::optional gcrGroupAddr) const { - if (auto it = m_recipientAgreements.find({originator, tid}); it != m_recipientAgreements.end()) + if (const auto it = GetRecipientBaAgreement(originator, tid, gcrGroupAddr); + it != m_recipientAgreements.end()) { return std::cref(it->second); } - return std::nullopt; } @@ -270,20 +304,37 @@ BlockAckManager::CreateRecipientAgreement(const MgtAddBaResponseHeader& respHdr, agreement.SetGcrGroupAddress(*gcrGroupAddr); } - m_recipientAgreements.insert_or_assign({originator, tid}, agreement); + if (auto it = GetRecipientBaAgreement(originator, tid, respHdr.GetGcrGroupAddress()); + it != m_recipientAgreements.end()) + { + it->second = std::move(agreement); + } + else + { + m_recipientAgreements.emplace(std::make_pair(originator, tid), std::move(agreement)); + } + + const auto [first, last] = m_recipientAgreements.equal_range({originator, tid}); + NS_ASSERT_MSG( + std::count_if(first, + last, + [&respHdr](const auto& elem) { + return elem.second.GetGcrGroupAddress() == respHdr.GetGcrGroupAddress(); + }) == 1, + "There exists more than one " << (respHdr.GetGcrGroupAddress().has_value() ? "GCR " : " ") + << "Block Ack agreement for originator " << originator + << " and tid " << +tid); } void BlockAckManager::DestroyRecipientAgreement(const Mac48Address& originator, uint8_t tid) { NS_LOG_FUNCTION(this << originator << tid); - - if (auto agreementIt = m_recipientAgreements.find({originator, tid}); - agreementIt != m_recipientAgreements.end()) + if (auto it = GetRecipientBaAgreement(originator, tid); it != m_recipientAgreements.end()) { // forward up the buffered MPDUs before destroying the agreement - agreementIt->second.Flush(); - m_recipientAgreements.erase(agreementIt); + it->second.Flush(); + m_recipientAgreements.erase(it); } } @@ -669,28 +720,29 @@ BlockAckManager::NotifyGotBlockAckRequest(const Mac48Address& originator, uint16_t startingSeq) { NS_LOG_FUNCTION(this << originator << tid << startingSeq); - auto it = m_recipientAgreements.find({originator, tid}); - if (it == m_recipientAgreements.end()) + if (auto it = GetRecipientBaAgreement(originator, tid); it != m_recipientAgreements.end()) { - return; + it->second.NotifyReceivedBar(startingSeq); } - it->second.NotifyReceivedBar(startingSeq); } void BlockAckManager::NotifyGotMpdu(Ptr mpdu) { NS_LOG_FUNCTION(this << *mpdu); - auto originator = mpdu->GetOriginal()->GetHeader().GetAddr2(); NS_ASSERT(mpdu->GetHeader().IsQosData()); - auto tid = mpdu->GetHeader().GetQosTid(); - - auto it = m_recipientAgreements.find({originator, tid}); - if (it == m_recipientAgreements.end()) + const auto originator = mpdu->GetOriginal()->GetHeader().GetAddr2(); + const auto tid = mpdu->GetHeader().GetQosTid(); + std::optional groupAddress; + if (const auto addr1 = mpdu->GetOriginal()->GetHeader().GetAddr1(); addr1.IsGroup()) { - return; + groupAddress = mpdu->begin()->second.GetDestinationAddr(); + } + if (auto it = GetRecipientBaAgreement(originator, tid, groupAddress); + it != m_recipientAgreements.end()) + { + it->second.NotifyReceivedMpdu(mpdu); } - it->second.NotifyReceivedMpdu(mpdu); } CtrlBAckRequestHeader diff --git a/src/wifi/model/block-ack-manager.h b/src/wifi/model/block-ack-manager.h index 579bf9908..01f8455d4 100644 --- a/src/wifi/model/block-ack-manager.h +++ b/src/wifi/model/block-ack-manager.h @@ -88,13 +88,16 @@ class BlockAckManager : public Object /** * @param originator MAC address of the originator * @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 originator, if it exists * * Check if we are the recipient of an existing block ack agreement with the given originator. */ - RecipientAgreementOptConstRef GetAgreementAsRecipient(const Mac48Address& originator, - uint8_t tid) const; + RecipientAgreementOptConstRef GetAgreementAsRecipient( + const Mac48Address& originator, + uint8_t tid, + std::optional gcrGroupAddr = std::nullopt) const; /** * @param reqHdr Relative Add block ack request (action frame). @@ -445,13 +448,17 @@ class BlockAckManager : public Object /// AgreementKey-indexed map of originator block ack agreements using OriginatorAgreements = std::multimap>; - /// typedef for an iterator for Agreements + /// An iterator for originator block ack agreements using OriginatorAgreementsI = OriginatorAgreements::iterator; - /// typedef for a const iterator for Agreements + /// A const iterator for originator block ack agreements using OriginatorAgreementsCI = OriginatorAgreements::const_iterator; /// AgreementKey-indexed map of recipient block ack agreements - using RecipientAgreements = std::map; + using RecipientAgreements = std::multimap; + /// An iterator for recipient block ack agreements + using RecipientAgreementsI = RecipientAgreements::iterator; + /// A const iterator for recipient block ack agreements + using RecipientAgreementsCI = RecipientAgreements::const_iterator; /** * @param recipient MAC address of the recipient @@ -477,6 +484,30 @@ class BlockAckManager : public Object uint8_t tid, std::optional gcrGroupAddr = std::nullopt) const; + /** + * @param originator MAC address of the originator + * @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 + */ + RecipientAgreementsI GetRecipientBaAgreement( + const Mac48Address& originator, + uint8_t tid, + std::optional gcrGroupAddr = std::nullopt); + + /** + * @param originator MAC address of the originator + * @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 + */ + RecipientAgreementsCI GetRecipientBaAgreement( + const Mac48Address& originator, + 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 d96749172..d2518898c 100644 --- a/src/wifi/model/ht/ht-frame-exchange-manager.cc +++ b/src/wifi/model/ht/ht-frame-exchange-manager.cc @@ -273,7 +273,8 @@ HtFrameExchangeManager::SendAddBaResponse(const MgtAddBaRequestHeader& reqHdr, reqHdr.GetStartingSequence(), m_rxMiddle); - auto agreement = GetBaManager(tid)->GetAgreementAsRecipient(originator, tid); + auto agreement = + GetBaManager(tid)->GetAgreementAsRecipient(originator, tid, reqHdr.GetGcrGroupAddress()); NS_ASSERT(agreement); if (respHdr.GetTimeout() != 0) { @@ -749,9 +750,11 @@ HtFrameExchangeManager::NotifyReceivedNormalAck(Ptr mpdu) MgtAddBaResponseHeader addBa; p->PeekHeader(addBa); auto tid = addBa.GetTid(); - NS_ASSERT_MSG(GetBaManager(tid)->GetAgreementAsRecipient(address, tid), - "Recipient BA agreement {" << address << ", " << +tid - << "} not found"); + NS_ASSERT_MSG( + GetBaManager(tid)->GetAgreementAsRecipient(address, + tid, + addBa.GetGcrGroupAddress()), + "Recipient BA agreement {" << address << ", " << +tid << "} not found"); m_pendingAddBaResp.erase({address, tid}); } }