wifi: Handle GCR Block Ack agreement teardown

This commit is contained in:
Sébastien Deronne
2023-10-24 20:53:50 +02:00
parent 99c446bd5a
commit 4586aee61e
6 changed files with 141 additions and 59 deletions

View File

@@ -215,10 +215,13 @@ BlockAckManager::CreateOriginatorAgreement(const MgtAddBaRequestHeader& reqHdr,
}
void
BlockAckManager::DestroyOriginatorAgreement(const Mac48Address& recipient, uint8_t tid)
BlockAckManager::DestroyOriginatorAgreement(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr)
{
NS_LOG_FUNCTION(this << recipient << tid);
if (auto it = GetOriginatorBaAgreement(recipient, tid); it != m_originatorAgreements.end())
NS_LOG_FUNCTION(this << recipient << tid << gcrGroupAddr.has_value());
if (auto it = GetOriginatorBaAgreement(recipient, tid, gcrGroupAddr);
it != m_originatorAgreements.end())
{
m_originatorAgreements.erase(it);
}
@@ -267,7 +270,8 @@ BlockAckManager::UpdateOriginatorAgreement(const MgtAddBaResponseHeader& respHdr
&BlockAckManager::InactivityTimeout,
this,
recipient,
tid);
tid,
respHdr.GetGcrGroupAddress());
}
}
m_unblockPackets(recipient, tid);
@@ -327,10 +331,13 @@ BlockAckManager::CreateRecipientAgreement(const MgtAddBaResponseHeader& respHdr,
}
void
BlockAckManager::DestroyRecipientAgreement(const Mac48Address& originator, uint8_t tid)
BlockAckManager::DestroyRecipientAgreement(const Mac48Address& originator,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr)
{
NS_LOG_FUNCTION(this << originator << tid);
if (auto it = GetRecipientBaAgreement(originator, tid); it != m_recipientAgreements.end())
NS_LOG_FUNCTION(this << originator << tid << gcrGroupAddr.has_value());
if (auto it = GetRecipientBaAgreement(originator, tid, gcrGroupAddr);
it != m_recipientAgreements.end())
{
// forward up the buffered MPDUs before destroying the agreement
it->second.Flush();
@@ -558,7 +565,12 @@ BlockAckManager::NotifyGotBlockAck(uint8_t linkId,
it->second.first.m_inactivityEvent.Cancel();
Time timeout = MicroSeconds(1024 * it->second.first.GetTimeout());
it->second.first.m_inactivityEvent =
Simulator::Schedule(timeout, &BlockAckManager::InactivityTimeout, this, recipient, tid);
Simulator::Schedule(timeout,
&BlockAckManager::InactivityTimeout,
this,
recipient,
tid,
std::nullopt);
}
NS_ASSERT(blockAck.IsCompressed() || blockAck.IsExtendedCompressed() || blockAck.IsMultiSta());
@@ -818,17 +830,21 @@ BlockAckManager::RemoveFromSendBarIfDataQueuedList(const Mac48Address& recipient
}
void
BlockAckManager::InactivityTimeout(const Mac48Address& recipient, uint8_t tid)
BlockAckManager::InactivityTimeout(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr)
{
NS_LOG_FUNCTION(this << recipient << tid);
m_blockAckInactivityTimeout(recipient, tid, true);
NS_LOG_FUNCTION(this << recipient << tid << gcrGroupAddr.has_value());
m_blockAckInactivityTimeout(recipient, tid, true, gcrGroupAddr);
}
void
BlockAckManager::NotifyOriginatorAgreementRejected(const Mac48Address& recipient, uint8_t tid)
BlockAckManager::NotifyOriginatorAgreementRejected(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr)
{
NS_LOG_FUNCTION(this << recipient << tid);
auto it = GetOriginatorBaAgreement(recipient, tid);
NS_LOG_FUNCTION(this << recipient << tid << gcrGroupAddr.has_value());
auto it = GetOriginatorBaAgreement(recipient, tid, gcrGroupAddr);
NS_ASSERT(it != m_originatorAgreements.end());
if (!it->second.first.IsRejected())
{
@@ -842,10 +858,12 @@ BlockAckManager::NotifyOriginatorAgreementRejected(const Mac48Address& recipient
}
void
BlockAckManager::NotifyOriginatorAgreementNoReply(const Mac48Address& recipient, uint8_t tid)
BlockAckManager::NotifyOriginatorAgreementNoReply(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr)
{
NS_LOG_FUNCTION(this << recipient << tid);
auto it = GetOriginatorBaAgreement(recipient, tid);
NS_LOG_FUNCTION(this << recipient << tid << gcrGroupAddr.has_value());
auto it = GetOriginatorBaAgreement(recipient, tid, gcrGroupAddr);
NS_ASSERT(it != m_originatorAgreements.end());
if (!it->second.first.IsNoReply())
{
@@ -859,10 +877,12 @@ BlockAckManager::NotifyOriginatorAgreementNoReply(const Mac48Address& recipient,
}
void
BlockAckManager::NotifyOriginatorAgreementReset(const Mac48Address& recipient, uint8_t tid)
BlockAckManager::NotifyOriginatorAgreementReset(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr)
{
NS_LOG_FUNCTION(this << recipient << tid);
auto it = GetOriginatorBaAgreement(recipient, tid);
NS_LOG_FUNCTION(this << recipient << tid << gcrGroupAddr.has_value());
auto it = GetOriginatorBaAgreement(recipient, tid, gcrGroupAddr);
NS_ASSERT(it != m_originatorAgreements.end());
if (!it->second.first.IsReset())
{
@@ -911,7 +931,8 @@ BlockAckManager::NeedBarRetransmission(uint8_t tid, const Mac48Address& recipien
}
void
BlockAckManager::SetBlockAckInactivityCallback(Callback<void, Mac48Address, uint8_t, bool> callback)
BlockAckManager::SetBlockAckInactivityCallback(
Callback<void, Mac48Address, uint8_t, bool, std::optional<Mac48Address>> callback)
{
NS_LOG_FUNCTION(this << &callback);
m_blockAckInactivityTimeout = callback;

View File

@@ -111,11 +111,14 @@ class BlockAckManager : public Object
/**
* @param recipient Address of peer station involved in block ack mechanism.
* @param tid traffic ID of transmitted packet.
* @param gcrGroupAddr the GCR Group Address (only if it a GCR Block Ack agreement)
*
* Invoked when a recipient reject a block ack agreement or when a DELBA frame
* is Received/Transmitted.
*/
void DestroyOriginatorAgreement(const Mac48Address& recipient, uint8_t tid);
void DestroyOriginatorAgreement(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr);
/**
* @param respHdr Relative Add block ack response (action frame).
* @param recipient Address of peer station involved in block ack mechanism.
@@ -152,8 +155,11 @@ class BlockAckManager : public Object
*
* @param originator the originator MAC address
* @param tid the TID associated with the Block Ack agreement
* @param gcrGroupAddr the GCR Group Address (only if it a GCR Block Ack agreement)
*/
void DestroyRecipientAgreement(const Mac48Address& originator, uint8_t tid);
void DestroyRecipientAgreement(const Mac48Address& originator,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr);
/**
* @param mpdu MPDU to store.
@@ -246,29 +252,38 @@ class BlockAckManager : public Object
/**
* @param recipient Address of peer station involved in block ack mechanism.
* @param tid Traffic ID of transmitted packet.
* @param gcrGroupAddr the GCR Group Address (only if it a GCR Block Ack agreement)
*
* Marks an originator agreement as rejected. This happens if <i>recipient</i> station reject
* block ack setup by an ADDBA Response frame with a failure status code. For now we assume
* that every QoS station accepts a block ack setup.
*/
void NotifyOriginatorAgreementRejected(const Mac48Address& recipient, uint8_t tid);
void NotifyOriginatorAgreementRejected(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr);
/**
* @param recipient Address of peer station involved in block ack mechanism.
* @param tid Traffic ID of transmitted packet.
* @param gcrGroupAddr the GCR Group Address (only if it a GCR Block Ack agreement)
*
* Marks an originator agreement after not receiving response to ADDBA request. During this
* state any packets in queue will be transmitted using normal MPDU. This also unblocks
* recipient address.
*/
void NotifyOriginatorAgreementNoReply(const Mac48Address& recipient, uint8_t tid);
void NotifyOriginatorAgreementNoReply(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr);
/**
* @param recipient Address of peer station involved in block ack mechanism.
* @param tid Traffic ID of transmitted packet.
* @param gcrGroupAddr the GCR Group Address (only if it a GCR Block Ack agreement)
*
* Set Originator BA agreement to a transitory state to reset it after not receiving response
* to ADDBA request.
*/
void NotifyOriginatorAgreementReset(const Mac48Address& recipient, uint8_t tid);
void NotifyOriginatorAgreementReset(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr);
/**
* @param nPackets Minimum number of packets for use of block ack.
*
@@ -287,7 +302,8 @@ class BlockAckManager : public Object
* Set block ack inactivity callback
* @param callback the block ack inactivity callback function
*/
void SetBlockAckInactivityCallback(Callback<void, Mac48Address, uint8_t, bool> callback);
void SetBlockAckInactivityCallback(
Callback<void, Mac48Address, uint8_t, bool, std::optional<Mac48Address>> callback);
/**
* Set block destination callback
* @param callback the block destination callback
@@ -456,11 +472,14 @@ class BlockAckManager : public Object
private:
/**
* Inactivity timeout function
* Inactivity timeout function for a Block Ack agreement
* @param recipient the recipient MAC address
* @param tid Traffic ID
* @param gcrGroupAddr the GCR Group Address (only if it a GCR Block Ack agreement)
*/
void InactivityTimeout(const Mac48Address& recipient, uint8_t tid);
void InactivityTimeout(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr);
/**
* typedef for a list of WifiMpdu.
@@ -569,7 +588,7 @@ class BlockAckManager : public Object
uint8_t m_blockAckThreshold; ///< block ack threshold
Ptr<WifiMacQueue> m_queue; ///< queue
Callback<void, Mac48Address, uint8_t, bool>
Callback<void, Mac48Address, uint8_t, bool, std::optional<Mac48Address>>
m_blockAckInactivityTimeout; ///< BlockAck inactivity timeout callback
Callback<void, Mac48Address, uint8_t> m_blockPackets; ///< block packets callback
Callback<void, Mac48Address, uint8_t> m_unblockPackets; ///< unblock packets callback

View File

@@ -286,7 +286,8 @@ HtFrameExchangeManager::SendAddBaResponse(const MgtAddBaRequestHeader& reqHdr,
this,
originator,
tid,
false);
false,
reqHdr.GetGcrGroupAddress());
}
auto mpdu = Create<WifiMpdu>(packet, hdr);
@@ -320,9 +321,12 @@ HtFrameExchangeManager::SendAddBaResponse(const MgtAddBaRequestHeader& reqHdr,
}
void
HtFrameExchangeManager::SendDelbaFrame(Mac48Address addr, uint8_t tid, bool byOriginator)
HtFrameExchangeManager::SendDelbaFrame(Mac48Address addr,
uint8_t tid,
bool byOriginator,
std::optional<Mac48Address> gcrGroupAddr)
{
NS_LOG_FUNCTION(this << addr << +tid << byOriginator);
NS_LOG_FUNCTION(this << addr << +tid << byOriginator << gcrGroupAddr.has_value());
WifiMacHeader hdr;
hdr.SetType(WIFI_MAC_MGT_ACTION);
// use the remote link address if addr is an MLD address
@@ -335,6 +339,10 @@ HtFrameExchangeManager::SendDelbaFrame(Mac48Address addr, uint8_t tid, bool byOr
MgtDelBaHeader delbaHdr;
delbaHdr.SetTid(tid);
byOriginator ? delbaHdr.SetByOriginator() : delbaHdr.SetByRecipient();
if (gcrGroupAddr.has_value())
{
delbaHdr.SetGcrGroupAddress(gcrGroupAddr.value());
}
WifiActionHeader actionHdr;
WifiActionHeader::ActionValue action;
@@ -725,11 +733,15 @@ HtFrameExchangeManager::NotifyReceivedNormalAck(Ptr<WifiMpdu> mpdu)
auto tid = delBa.GetTid();
if (delBa.IsByOriginator())
{
GetBaManager(tid)->DestroyOriginatorAgreement(address, tid);
GetBaManager(tid)->DestroyOriginatorAgreement(address,
tid,
delBa.GetGcrGroupAddress());
}
else
{
GetBaManager(tid)->DestroyRecipientAgreement(address, tid);
GetBaManager(tid)->DestroyRecipientAgreement(address,
tid,
delBa.GetGcrGroupAddress());
}
}
else if (actionHdr.GetAction().blockAck == WifiActionHeader::BLOCK_ACK_ADDBA_REQUEST)
@@ -742,7 +754,8 @@ HtFrameExchangeManager::NotifyReceivedNormalAck(Ptr<WifiMpdu> mpdu)
&QosTxop::AddBaResponseTimeout,
edca,
address,
addBa.GetTid());
addBa.GetTid(),
addBa.GetGcrGroupAddress());
}
else if (actionHdr.GetAction().blockAck == WifiActionHeader::BLOCK_ACK_ADDBA_RESPONSE)
{
@@ -828,12 +841,15 @@ HtFrameExchangeManager::NotifyPacketDiscarded(Ptr<const WifiMpdu> mpdu)
{
NS_LOG_DEBUG("No ACK after ADDBA request");
Ptr<QosTxop> qosTxop = m_mac->GetQosTxop(tid);
qosTxop->NotifyOriginatorAgreementNoReply(recipient, tid);
qosTxop->NotifyOriginatorAgreementNoReply(recipient,
tid,
addBa.GetGcrGroupAddress());
Simulator::Schedule(qosTxop->GetFailedAddBaTimeout(),
&QosTxop::ResetBa,
qosTxop,
recipient,
tid);
tid,
addBa.GetGcrGroupAddress());
}
}
}
@@ -1769,7 +1785,9 @@ HtFrameExchangeManager::ReceiveMgtAction(Ptr<const WifiMpdu> mpdu, const WifiTxV
// agreement exists in BlockAckManager and we need to
// destroy it.
GetBaManager(delBaHdr.GetTid())
->DestroyRecipientAgreement(recipient, delBaHdr.GetTid());
->DestroyRecipientAgreement(recipient,
delBaHdr.GetTid(),
delBaHdr.GetGcrGroupAddress());
}
else
{

View File

@@ -138,8 +138,12 @@ class HtFrameExchangeManager : public QosFrameExchangeManager
* @param addr address of the recipient.
* @param tid traffic ID.
* @param byOriginator flag to indicate whether this is set by the originator.
* @param gcrGroupAddr the GCR Group Address (only if it a GCR Block Ack agreement)
*/
void SendDelbaFrame(Mac48Address addr, uint8_t tid, bool byOriginator);
void SendDelbaFrame(Mac48Address addr,
uint8_t tid,
bool byOriginator,
std::optional<Mac48Address> gcrGroupAddr);
/**
* Get the next BlockAckRequest or MU-BAR Trigger Frame to send, if any. If TID and recipient

View File

@@ -680,7 +680,9 @@ QosTxop::GotAddBaResponse(const MgtAddBaResponseHeader& respHdr, Mac48Address re
else
{
NS_LOG_DEBUG("discard ADDBA response" << recipient);
m_baManager->NotifyOriginatorAgreementRejected(recipient, tid);
m_baManager->NotifyOriginatorAgreementRejected(recipient,
tid,
respHdr.GetGcrGroupAddress());
}
}
@@ -689,14 +691,18 @@ QosTxop::GotDelBaFrame(const MgtDelBaHeader* delBaHdr, Mac48Address recipient)
{
NS_LOG_FUNCTION(this << delBaHdr << recipient);
NS_LOG_DEBUG("received DELBA frame from=" << recipient);
m_baManager->DestroyOriginatorAgreement(recipient, delBaHdr->GetTid());
m_baManager->DestroyOriginatorAgreement(recipient,
delBaHdr->GetTid(),
delBaHdr->GetGcrGroupAddress());
}
void
QosTxop::NotifyOriginatorAgreementNoReply(const Mac48Address& recipient, uint8_t tid)
QosTxop::NotifyOriginatorAgreementNoReply(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr)
{
NS_LOG_FUNCTION(this << recipient << tid);
m_baManager->NotifyOriginatorAgreementNoReply(recipient, tid);
NS_LOG_FUNCTION(this << recipient << tid << gcrGroupAddr.has_value());
m_baManager->NotifyOriginatorAgreementNoReply(recipient, tid, gcrGroupAddr);
}
void
@@ -742,30 +748,37 @@ QosTxop::GetBlockAckInactivityTimeout() const
}
void
QosTxop::AddBaResponseTimeout(Mac48Address recipient, uint8_t tid)
QosTxop::AddBaResponseTimeout(Mac48Address recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr)
{
NS_LOG_FUNCTION(this << recipient << +tid);
NS_LOG_FUNCTION(this << recipient << +tid << gcrGroupAddr.has_value());
// If agreement is still pending, ADDBA response is not received
if (auto agreement = m_baManager->GetAgreementAsOriginator(recipient, tid);
agreement && agreement->get().IsPending())
auto agreement = m_baManager->GetAgreementAsOriginator(recipient, tid, gcrGroupAddr);
if (agreement && agreement->get().IsPending())
{
NotifyOriginatorAgreementNoReply(recipient, tid);
Simulator::Schedule(m_failedAddBaTimeout, &QosTxop::ResetBa, this, recipient, tid);
NotifyOriginatorAgreementNoReply(recipient, tid, gcrGroupAddr);
Simulator::Schedule(m_failedAddBaTimeout,
&QosTxop::ResetBa,
this,
recipient,
tid,
gcrGroupAddr);
}
}
void
QosTxop::ResetBa(Mac48Address recipient, uint8_t tid)
QosTxop::ResetBa(Mac48Address recipient, uint8_t tid, std::optional<Mac48Address> gcrGroupAddr)
{
NS_LOG_FUNCTION(this << recipient << +tid);
NS_LOG_FUNCTION(this << recipient << +tid << gcrGroupAddr.has_value());
// This function is scheduled when waiting for an ADDBA response. However,
// before this function is called, a DELBA request may arrive, which causes
// the agreement to be deleted. Hence, check if an agreement exists before
// notifying that the agreement has to be reset.
if (auto agreement = m_baManager->GetAgreementAsOriginator(recipient, tid);
agreement && !agreement->get().IsEstablished())
auto agreement = m_baManager->GetAgreementAsOriginator(recipient, tid, gcrGroupAddr);
if (agreement && !agreement->get().IsEstablished())
{
m_baManager->NotifyOriginatorAgreementReset(recipient, tid);
m_baManager->NotifyOriginatorAgreementReset(recipient, tid, gcrGroupAddr);
}
}

View File

@@ -143,22 +143,29 @@ class QosTxop : public Txop
*
* @param recipient the intended recipient of the ADDBA_REQUEST frame
* @param tid the TID
* @param gcrGroupAddr the GCR Group Address (only if it a GCR Block Ack agreement)
*/
void NotifyOriginatorAgreementNoReply(const Mac48Address& recipient, uint8_t tid);
void NotifyOriginatorAgreementNoReply(const Mac48Address& recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr);
/**
* Callback when ADDBA response is not received after timeout.
*
* @param recipient MAC address of recipient
* @param tid traffic ID
* @param gcrGroupAddr the GCR Group Address (only if it a GCR Block Ack agreement)
*/
void AddBaResponseTimeout(Mac48Address recipient, uint8_t tid);
void AddBaResponseTimeout(Mac48Address recipient,
uint8_t tid,
std::optional<Mac48Address> gcrGroupAddr);
/**
* Reset BA agreement after BA negotiation failed.
*
* @param recipient MAC address of recipient
* @param tid traffic ID
* @param gcrGroupAddr the GCR Group Address (only if it a GCR Block Ack agreement)
*/
void ResetBa(Mac48Address recipient, uint8_t tid);
void ResetBa(Mac48Address recipient, uint8_t tid, std::optional<Mac48Address> gcrGroupAddr);
/**
* Set threshold for block ack mechanism. If number of packets in the