20#include "ns3/simulator.h"
36 TypeId(
"ns3::BlockAckManager")
40 .AddTraceSource(
"AgreementState",
41 "The state of the ADDBA handshake",
43 "ns3::BlockAckManager::AgreementStateTracedCallback");
139 return std::cref(
it->second.first);
152 return std::cref(
it->second);
162 const auto tid =
reqHdr.GetTid();
172 if (
reqHdr.IsImmediateBlockAck())
194 NS_ASSERT_MSG(
it->second.first.IsReset(),
"Existing agreement must be in RESET state");
207 return elem.second.first.GetGcrGroupAddress() ==
208 reqHdr.GetGcrGroupAddress();
210 "There exists more than one "
211 << (
reqHdr.GetGcrGroupAddress().has_value() ?
"GCR " :
" ")
212 <<
"Block Ack agreement for recipient " <<
recipient <<
" and tid " << +tid);
236 const auto tid =
respHdr.GetTid();
246 if (
respHdr.IsImmediateBlockAck())
259 if (!
it->second.first.IsEstablished())
278 if (!
respHdr.GetGcrGroupAddress().has_value())
286 if (
agreement.second.first.GetGcrGroupAddress() !=
respHdr.GetGcrGroupAddress())
290 if (!
agreement.second.first.IsEstablished())
307 const auto tid =
respHdr.GetTid();
318 if (
respHdr.IsImmediateBlockAck())
346 return elem.second.GetGcrGroupAddress() ==
respHdr.GetGcrGroupAddress();
348 "There exists more than one " << (
respHdr.GetGcrGroupAddress().has_value() ?
"GCR " :
" ")
349 <<
"Block Ack agreement for originator " <<
originator
350 <<
" and tid " << +tid);
391 NS_ASSERT(mpdu->GetHeader().IsQosData());
393 const auto tid = mpdu->GetHeader().GetQosTid();
398 agreementIt->second.first.GetDistance(mpdu->GetHeader().GetSequenceNumber());
411 if (mpdu->GetHeader().GetSequenceControl() == (*it)->GetHeader().GetSequenceControl())
413 NS_LOG_DEBUG(
"Packet already in the queue of the BA agreement");
418 agreementIt->second.first.GetDistance((*it)->GetHeader().GetSequenceNumber());
421 (*it)->GetHeader().GetFragmentNumber()))
429 agreementIt->second.first.NotifyTransmittedMpdu(mpdu);
455 if (!(*mpduIt)->IsQueued())
459 NS_LOG_DEBUG(
"MPDU is not stored in the EDCA queue, drop MPDU");
460 return it->second.second.erase(
mpduIt);
466 return it->second.second.erase(
mpduIt);
476 NS_LOG_DEBUG(
"Old packet. Remove from the EDCA queue, too");
480 return it->second.second.erase(
mpduIt);
483 std::optional<PacketQueueI>
prevIt;
484 if (
mpduIt !=
it->second.second.begin())
495 return (
prevIt.has_value() ? std::next(
prevIt.value()) :
it->second.second.begin());
505 (*mpduIt)->GetHeader().SetRetry();
506 (*mpduIt)->ResetInFlight(linkId);
508 return it->second.second.erase(
mpduIt);
515 NS_ASSERT(mpdu->GetHeader().IsQosData());
517 const auto recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
518 const auto tid = mpdu->GetHeader().GetQosTid();
524 it->second.first.NotifyAckedMpdu(mpdu);
533 if ((*queueIt)->GetHeader().GetSequenceNumber() == mpdu->GetHeader().GetSequenceNumber())
547 NS_ASSERT(mpdu->GetHeader().IsQosData());
548 const auto tid = mpdu->GetHeader().GetQosTid();
555 it->second.first.NotifyAckedMpdu(mpdu);
563 NS_ASSERT(mpdu->GetHeader().IsQosData());
565 const auto recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
566 const auto tid = mpdu->GetHeader().GetQosTid();
576 if ((*queueIt)->GetHeader().GetSequenceNumber() == mpdu->GetHeader().GetSequenceNumber())
584std::pair<uint16_t, uint16_t>
588 const std::set<uint8_t>&
tids,
614 if (
it->second.first.m_inactivityEvent.IsPending())
619 it->second.first.m_inactivityEvent.Cancel();
621 it->second.first.m_inactivityEvent =
632 std::list<Ptr<const WifiMpdu>> acked;
636 uint16_t
currentSeq = (*queueIt)->GetHeader().GetSequenceNumber();
640 it->second.first.NotifyAckedMpdu(*
queueIt);
656 m_queue->DequeueIfQueued(acked);
663 auto linkIds = (*queueIt)->GetInFlightLinkIds();
665 if (linkIds.size() == 1 && *linkIds.begin() == linkId)
682std::optional<std::pair<uint16_t, uint16_t>>
691 "Received GCR Block Ack response from unexpected recipient");
701 it->second.first.GetGcrGroupAddress().value() ==
704 if (
it->second.first.m_inactivityEvent.IsPending())
709 it->second.first.m_inactivityEvent.Cancel();
711 it->second.first.m_inactivityEvent =
732 std::vector<bool> acked;
735 auto currentSeq = (*queueIt)->GetHeader().GetSequenceNumber();
737 auto received =
true;
742 acked.emplace_back(received);
752 std::size_t index = 0;
754 NS_ASSERT(acked.size() ==
it->second.second.size());
757 if (acked.at(index++))
759 it->second.first.NotifyAckedMpdu(*
queueIt);
791 auto linkIds = (*queueIt)->GetInFlightLinkIds();
793 if (linkIds.size() == 1 && *linkIds.begin() == linkId)
831 for (
auto mpduIt =
it->second.second.begin();
mpduIt !=
it->second.second.end();)
834 auto linkIds = (*mpduIt)->GetInFlightLinkIds();
835 if (!linkIds.contains(linkId))
848 if (!mpdu->GetHeader().IsQosData())
854 if (!mpdu->GetHeader().IsRetry() && !mpdu->IsInFlight())
860 const auto recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
861 const auto tid = mpdu->GetHeader().GetQosTid();
869 const auto groupAddress = mpdu->GetOriginal()->GetHeader().GetAddr1();
872 if (
it->first.second != tid || !
it->second.first.GetGcrGroupAddress().has_value() ||
906 if (
baAgreement.GetDistance((*mpduIt)->GetHeader().GetSequenceNumber()) >=
931 hdr.SetAddr2(mpdu->GetOriginal()->GetHeader().GetAddr2());
935 hdr.SetNoMoreFragments();
958 NS_ASSERT(mpdu->GetHeader().IsQosData());
959 const auto originator = mpdu->GetOriginal()->GetHeader().GetAddr2();
960 const auto tid = mpdu->GetHeader().GetQosTid();
962 if (
const auto addr1 = mpdu->GetOriginal()->GetHeader().GetAddr1();
addr1.IsGroup())
965 mpdu->GetHeader().IsQosAmsdu() ? mpdu->begin()->second.GetDestinationAddr() :
addr1;
970 it->second.NotifyReceivedMpdu(mpdu);
989 reqHdr.SetType((*it).second.first.GetBlockAckReqType());
992 reqHdr.SetStartingSequence((*it).second.first.GetStartingSequence());
1001 uint8_t tid =
reqHdr.GetTidInfo();
1011 if (
item->GetHeader().IsBlockAckReq() &&
item->GetHeader().GetAddr1() ==
hdr.GetAddr1())
1028const std::list<BlockAckManager::AgreementKey>&
1071 if (!
it->second.first.IsRejected())
1093 if (!
it->second.first.IsNoReply())
1115 if (!
it->second.first.IsReset())
1150 for (
auto mpduIt =
it->second.second.begin();
mpduIt !=
it->second.second.end();)
1155 if (
mpduIt !=
it->second.second.begin())
1231 uint16_t seqNum = 0;
1234 if (key.second != tid)
1240 seqNum =
pair.first.GetStartingSequence();
1255 uint16_t
gcrBufferSize = std::numeric_limits<uint16_t>::max();
1258 if ((key.second == tid) && (
pair.first.GetGcrGroupAddress() ==
groupAddress))
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
Manages all block ack agreements for an originator station.
std::optional< std::pair< uint16_t, uint16_t > > NotifyGotGcrBlockAck(uint8_t linkId, const CtrlBAckResponseHeader &blockAck, const Mac48Address &recipient, const GcrManager::GcrMembers &members)
void SetTxFailedCallback(TxFailed callback)
std::pair< Mac48Address, uint8_t > AgreementKey
agreement key typedef (MAC address and TID)
void UpdateOriginatorAgreement(const MgtAddBaResponseHeader &respHdr, const Mac48Address &recipient, uint16_t startingSeq)
Callback< void, Mac48Address, uint8_t > m_unblockPackets
unblock packets callback
OriginatorAgreements::iterator OriginatorAgreementsI
An iterator for originator block ack agreements.
void SetQueue(const Ptr< WifiMacQueue > queue)
void SetTxOkCallback(TxOk callback)
std::map< Mac48Address, CtrlBAckResponseHeader > GcrBlockAcks
List of received GCR BlockAck frames indexed by originator.
OriginatorAgreementsI GetOriginatorBaAgreement(const Mac48Address &recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr=std::nullopt)
CtrlBAckRequestHeader GetBlockAckReqHeader(const Mac48Address &recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr=std::nullopt) const
void NotifyOriginatorAgreementNoReply(const Mac48Address &recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr)
uint8_t m_blockAckThreshold
block ack threshold
void NotifyLastGcrUrTx(Ptr< const WifiMpdu > mpdu, const GcrManager::GcrMembers &recipients)
Notify the block ack manager about the last groupcast MPDU transmitted with the GCR-UR service.
RecipientAgreements m_recipientAgreements
Recipient Block Ack agreements.
std::optional< std::reference_wrapper< const OriginatorBlockAckAgreement > > OriginatorAgreementOptConstRef
optional const reference to OriginatorBlockAckAgreement
~BlockAckManager() override
static TypeId GetTypeId()
Get the type ID.
TracedCallback< Time, Mac48Address, uint8_t, OriginatorBlockAckAgreement::State > m_originatorAgreementState
The trace source fired when a state transition occurred.
void SetBlockAckThreshold(uint8_t nPackets)
DroppedOldMpdu m_droppedOldMpduCallback
the dropped MPDU callback
std::optional< std::reference_wrapper< const RecipientBlockAckAgreement > > RecipientAgreementOptConstRef
optional const reference to RecipientBlockAckAgreement
void SetDroppedOldMpduCallback(DroppedOldMpdu callback)
std::list< Ptr< WifiMpdu > >::iterator PacketQueueI
typedef for an iterator for PacketQueue.
TxFailed m_txFailedCallback
transmit failed callback
void SetUnblockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
Set unblock destination callback.
Ptr< WifiMacQueue > m_queue
queue
RecipientAgreements::iterator RecipientAgreementsI
An iterator for recipient block ack agreements.
uint16_t GetRecipientBufferSize(const Mac48Address &recipient, uint8_t tid) const
This function returns the buffer size negotiated with the recipient.
void NotifyOriginatorAgreementRejected(const Mac48Address &recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr)
void CreateOriginatorAgreement(const MgtAddBaRequestHeader &reqHdr, const Mac48Address &recipient)
void CreateRecipientAgreement(const MgtAddBaResponseHeader &respHdr, const Mac48Address &originator, uint16_t startingSeq, Ptr< MacRxMiddle > rxMiddle)
std::list< Ptr< WifiMpdu > > PacketQueue
typedef for a list of WifiMpdu.
Callback< void, Mac48Address, uint8_t, bool, std::optional< Mac48Address > > m_blockAckInactivityTimeout
BlockAck inactivity timeout callback.
OriginatorAgreements::const_iterator OriginatorAgreementsCI
A const iterator for originator block ack agreements.
void DestroyOriginatorAgreement(const Mac48Address &recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr)
bool NeedGcrBarRetransmission(const Mac48Address &gcrGroupAddress, const Mac48Address &recipient, uint8_t tid) const
This function returns true if a GCR block ack agreement is established with the given recipient,...
void NotifyMissedBlockAck(uint8_t linkId, const Mac48Address &recipient, uint8_t tid)
OriginatorAgreements m_originatorAgreements
This data structure contains, for each originator block ack agreement (recipient, TID),...
void StorePacket(Ptr< WifiMpdu > mpdu)
void RemoveFromSendBarIfDataQueuedList(const Mac48Address &recipient, uint8_t tid)
Remove the given (recipient, TID) pair from the list of BA agreements for which a BAR shall only be s...
void NotifyGotAck(uint8_t linkId, Ptr< const WifiMpdu > mpdu)
Invoked upon receipt of an Ack frame on the given link after the transmission of a QoS data frame sen...
void AddToSendBarIfDataQueuedList(const Mac48Address &recipient, uint8_t tid)
Add the given (recipient, TID) pair to the list of BA agreements for which a BAR shall only be sent i...
void NotifyDiscardedMpdu(Ptr< const WifiMpdu > mpdu)
bool IsGcrAgreementEstablished(const Mac48Address &gcrGroupAddress, uint8_t tid, const GcrManager::GcrMembers &members) const
Check if a GCR Block Ack agreement has been successfully established with all members of the group.
void NotifyGotMpdu(Ptr< const WifiMpdu > mpdu)
void HandleDiscardedMpdu(Ptr< const WifiMpdu > mpdu, OriginatorAgreementsI iter)
Handle discarded MPDU by making the transmit window advance beyond the discarded frame.
bool NeedBarRetransmission(uint8_t tid, const Mac48Address &recipient)
This function returns true if a block ack agreement is established with the given recipient for the g...
void SetBlockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
Set block destination callback.
void NotifyOriginatorAgreementReset(const Mac48Address &recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr)
std::list< AgreementKey > m_sendBarIfDataQueued
list of BA agreements for which a BAR shall only be sent if data is queued
void DestroyRecipientAgreement(const Mac48Address &originator, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr)
Destroy a recipient Block Ack agreement.
uint32_t GetNBufferedPackets(const Mac48Address &recipient, uint8_t tid) const
PacketQueueI HandleInFlightMpdu(uint8_t linkId, PacketQueueI mpduIt, MpduStatus status, const OriginatorAgreementsI &it, const Time &now)
Handle the given in flight MPDU based on its given status.
void SetBlockAckInactivityCallback(Callback< void, Mac48Address, uint8_t, bool, std::optional< Mac48Address > > callback)
Set block ack inactivity callback.
OriginatorAgreementOptConstRef GetAgreementAsOriginator(const Mac48Address &recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr=std::nullopt) const
RecipientAgreements::const_iterator RecipientAgreementsCI
A const iterator for recipient block ack agreements.
uint16_t GetOriginatorStartingSequence(const Mac48Address &recipient, uint8_t tid) const
This function returns the starting sequence number of the transmit window.
void NotifyGotBlockAckRequest(const Mac48Address &originator, uint8_t tid, uint16_t startingSeq, std::optional< Mac48Address > gcrGroupAddr=std::nullopt)
uint16_t GetGcrStartingSequence(const Mac48Address &groupAddress, uint8_t tid) const
This function returns the starting sequence number of the transmit window for a given GCR Block Ack a...
uint16_t GetGcrBufferSize(const Mac48Address &groupAddress, uint8_t tid) const
This function returns the minimum buffer size from ADDBA Response frames sent by all members of a gro...
TxOk m_txOkCallback
transmit OK callback
MpduStatus
Enumeration for the statuses of a buffered MPDU.
std::pair< uint16_t, uint16_t > NotifyGotBlockAck(uint8_t linkId, const CtrlBAckResponseHeader &blockAck, const Mac48Address &recipient, const std::set< uint8_t > &tids, size_t index=0)
void DoDispose() override
Destructor implementation.
void ScheduleBar(const CtrlBAckRequestHeader &reqHdr, const WifiMacHeader &hdr)
void InactivityTimeout(const Mac48Address &recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr)
Inactivity timeout function for a Block Ack agreement.
Callback< void, Mac48Address, uint8_t > m_blockPackets
block packets callback
void DoStorePacket(Ptr< WifiMpdu > mpdu, const Mac48Address &recipient, std::optional< Mac48Address > gcrGroupAddr=std::nullopt)
void StoreGcrPacket(Ptr< WifiMpdu > mpdu, const GcrManager::GcrMembers &members)
RecipientAgreementsI GetRecipientBaAgreement(const Mac48Address &originator, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr=std::nullopt)
RecipientAgreementOptConstRef GetAgreementAsRecipient(const Mac48Address &originator, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr=std::nullopt) const
const std::list< AgreementKey > & GetSendBarIfDataQueuedList() const
std::map< Mac48Address, GcrBlockAcks > m_gcrBlockAcks
received GCR Block ACKs
void NotifyMissedAck(uint8_t linkId, Ptr< WifiMpdu > mpdu)
Invoked upon missed reception of an Ack frame on the given link after the transmission of a QoS data ...
bool IsNull() const
Check for null implementation.
std::unordered_set< Mac48Address, WifiAddressHash > GcrMembers
MAC addresses of member STAs of a GCR group.
A base class which provides memory management and object aggregation.
Maintains the state and information about transmitted MPDUs with Ack Policy set to Block Ack for an o...
Smart pointer class similar to boost::intrusive_ptr.
Maintains the scoreboard and the receive reordering buffer used by a recipient of a Block Ack agreeme...
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now()
Return the current simulation virtual time.
Simulation virtual time values and global simulation resolution.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
bool QosUtilsIsOldPacket(uint16_t startingSeq, uint16_t seqNumber)
This function checks if packet with sequence number seqNumber is an "old" packet.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static constexpr uint16_t SEQNO_SPACE_HALF_SIZE
Size of the half the space of sequence numbers (used to determine old packets)
std::tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
static constexpr uint8_t SINGLE_LINK_OP_ID
Link ID for single link operations (helps tracking places where correct link ID is to be used to supp...