wifi: Use multimap for recipient block agreements
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user