wifi: Use multimap for recipient block agreements

This commit is contained in:
Sébastien Deronne
2025-01-17 12:36:37 +01:00
parent f42436a9b8
commit bc0a9b5969
3 changed files with 115 additions and 29 deletions

View File

@@ -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<Mac48Address> 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<Mac48Address> 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<Mac48Address> 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<const WifiMpdu> 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<Mac48Address> 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

View File

@@ -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<Mac48Address> 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<AgreementKey, std::pair<OriginatorBlockAckAgreement, PacketQueue>>;
/// 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<AgreementKey, RecipientBlockAckAgreement>;
using RecipientAgreements = std::multimap<AgreementKey, RecipientBlockAckAgreement>;
/// 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<Mac48Address> 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<Mac48Address> 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<Mac48Address> 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

View File

@@ -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<WifiMpdu> 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});
}
}