wifi: Establish block ack agreement with all GCR member STAs prior to a groupcast transmission

This commit is contained in:
Sébastien Deronne
2023-09-19 21:28:05 +02:00
parent 75c8da6cfc
commit 03b6be6b55
2 changed files with 88 additions and 8 deletions

View File

@@ -11,8 +11,10 @@
#include "ht-configuration.h"
#include "ns3/abort.h"
#include "ns3/ap-wifi-mac.h"
#include "ns3/assert.h"
#include "ns3/ctrl-headers.h"
#include "ns3/gcr-manager.h"
#include "ns3/log.h"
#include "ns3/mgt-action-headers.h"
#include "ns3/recipient-block-ack-agreement.h"
@@ -134,6 +136,43 @@ HtFrameExchangeManager::NeedSetupBlockAck(Mac48Address recipient, uint8_t tid)
return establish;
}
std::optional<Mac48Address>
HtFrameExchangeManager::NeedSetupGcrBlockAck(const WifiMacHeader& header)
{
NS_ASSERT(m_mac->GetTypeOfStation() == AP && m_apMac->UseGcr(header));
const auto& groupAddress = header.GetAddr1();
const auto tid = header.GetQosTid();
auto qosTxop = m_mac->GetQosTxop(tid);
const auto maxMpduSize =
m_mpduAggregator->GetMaxAmpduSize(groupAddress, tid, WIFI_MOD_CLASS_HT);
WifiContainerQueueId queueId{WIFI_QOSDATA_QUEUE, WIFI_GROUPCAST, groupAddress, tid};
for (const auto& recipients =
m_apMac->GetGcrManager()->GetMemberStasForGroupAddress(groupAddress);
const auto& nextRecipient : recipients)
{
if (auto agreement =
qosTxop->GetBaManager()->GetAgreementAsOriginator(nextRecipient, tid, groupAddress);
agreement && !agreement->get().IsReset())
{
continue;
}
const auto packets = qosTxop->GetWifiMacQueue()->GetNPackets(queueId);
const auto establish =
((qosTxop->GetBlockAckThreshold() > 0 && packets >= qosTxop->GetBlockAckThreshold()) ||
(maxMpduSize > 0 && packets > 1));
NS_LOG_FUNCTION(this << groupAddress << +tid << establish);
if (establish)
{
return nextRecipient;
}
}
return std::nullopt;
}
bool
HtFrameExchangeManager::SendAddBaRequest(Mac48Address dest,
uint8_t tid,
@@ -356,6 +395,17 @@ HtFrameExchangeManager::SendDelbaFrame(Mac48Address addr,
m_mac->GetQosTxop(tid)->Queue(Create<WifiMpdu>(packet, hdr));
}
uint16_t
HtFrameExchangeManager::GetBaAgreementStartingSequenceNumber(const WifiMacHeader& header)
{
// if the peeked MPDU has been already transmitted, use its sequence number
// as the starting sequence number for the BA agreement, otherwise use the
// next available sequence number
return header.IsRetry()
? header.GetSequenceNumber()
: m_txMiddle->GetNextSeqNumberByTidAndAddress(header.GetQosTid(), header.GetAddr1());
}
bool
HtFrameExchangeManager::StartFrameExchange(Ptr<QosTxop> edca, Time availableTime, bool initialFrame)
{
@@ -384,20 +434,26 @@ HtFrameExchangeManager::StartFrameExchange(Ptr<QosTxop> edca, Time availableTime
if (hdr.IsQosData() && !hdr.GetAddr1().IsGroup() &&
NeedSetupBlockAck(hdr.GetAddr1(), hdr.GetQosTid()))
{
// if the peeked MPDU has been already transmitted, use its sequence number
// as the starting sequence number for the BA agreement, otherwise use the
// next available sequence number
uint16_t startingSeq =
(hdr.IsRetry()
? hdr.GetSequenceNumber()
: m_txMiddle->GetNextSeqNumberByTidAndAddress(hdr.GetQosTid(), hdr.GetAddr1()));
return SendAddBaRequest(hdr.GetAddr1(),
hdr.GetQosTid(),
startingSeq,
GetBaAgreementStartingSequenceNumber(hdr),
edca->GetBlockAckInactivityTimeout(),
true,
availableTime);
}
else if (IsGcr(m_mac, hdr))
{
if (const auto addbaRecipient = NeedSetupGcrBlockAck(hdr))
{
return SendAddBaRequest(addbaRecipient.value(),
hdr.GetQosTid(),
GetBaAgreementStartingSequenceNumber(hdr),
edca->GetBlockAckInactivityTimeout(),
true,
availableTime,
hdr.GetAddr1());
}
}
// Use SendDataFrame if we can try aggregation
if (hdr.IsQosData() && !hdr.GetAddr1().IsGroup() && !peekedItem->IsFragment() &&

View File

@@ -281,6 +281,15 @@ class HtFrameExchangeManager : public QosFrameExchangeManager
*/
virtual bool SendDataFrame(Ptr<WifiMpdu> peekedItem, Time availableTime, bool initialFrame);
/**
* Retrieve the starting sequence number for a BA agreement to be established.
*
* @param header the MAC header of the next data packet selected for transmission once the BA
* agreement is established. \return the starting sequence number for a BA agreement to be
* established
*/
uint16_t GetBaAgreementStartingSequenceNumber(const WifiMacHeader& header);
/**
* A Block Ack agreement needs to be established with the given recipient for the
* given TID if it does not already exist (or exists and is in state RESET) and:
@@ -295,6 +304,21 @@ class HtFrameExchangeManager : public QosFrameExchangeManager
*/
virtual bool NeedSetupBlockAck(Mac48Address recipient, uint8_t tid);
/**
* A Block Ack agreement needs to be established prior to the transmission of a groupcast data
* packet using the GCR service if it does not already exist (or exists and is in state RESET)
* for all member STAs and:
*
* - the number of packets in the groupcast queue reaches the BlockAckThreshold value OR
* - MPDU aggregation is enabled and there is more than one groupcast packet in the queue OR
* - the station is a VHT station
*
* @param header the MAC header of the next groupcast data packet selected for transmission.
* @return the recipient of the ADDBA frame if a Block Ack agreement needs to be established,
* std::nullopt otherwise.
*/
virtual std::optional<Mac48Address> NeedSetupGcrBlockAck(const WifiMacHeader& header);
/**
* Sends an ADDBA Request to establish a block ack agreement with STA
* addressed by <i>recipient</i> for TID <i>tid</i>.