20#include "ns3/simulator.h"
36 TypeId(
"ns3::BlockAckManager")
40 .AddTraceSource(
"AgreementState",
41 "The state of the ADDBA handshake",
43 "ns3::BlockAckManager::AgreementStateTracedCallback");
70 return std::cref(it->second.first);
81 return std::cref(it->second);
92 const auto tid = reqHdr.
GetTid();
122 "Existing agreement must be in RESET state");
125 std::make_pair(std::move(agreement),
PacketQueue{}));
143 uint16_t startingSeq)
146 uint8_t tid = respHdr.
GetTid();
168 if (!it->second.first.IsEstablished())
192 uint16_t startingSeq,
195 NS_LOG_FUNCTION(
this << respHdr << originator << startingSeq << rxMiddle);
196 const auto tid = respHdr.
GetTid();
232 agreementIt->second.Flush();
241 NS_ASSERT(mpdu->GetHeader().IsQosData());
243 uint8_t tid = mpdu->GetHeader().GetQosTid();
250 agreementIt->second.first.GetDistance(mpdu->GetHeader().GetSequenceNumber());
260 auto it = agreementIt->second.second.rbegin();
261 while (it != agreementIt->second.second.rend())
263 if (mpdu->GetHeader().GetSequenceControl() == (*it)->GetHeader().GetSequenceControl())
265 NS_LOG_DEBUG(
"Packet already in the queue of the BA agreement");
270 agreementIt->second.first.GetDistance((*it)->GetHeader().GetSequenceNumber());
272 if (mpduDist > dist || (mpduDist == dist && mpdu->GetHeader().GetFragmentNumber() >
273 (*it)->GetHeader().GetFragmentNumber()))
280 agreementIt->second.second.insert(it.base(), mpdu);
281 agreementIt->second.first.NotifyTransmittedMpdu(mpdu);
292 return it->second.second.size();
309 NS_LOG_FUNCTION(
this << linkId << **mpduIt <<
static_cast<uint8_t
>(status));
311 if (!(*mpduIt)->IsQueued())
315 NS_LOG_DEBUG(
"MPDU is not stored in the EDCA queue, drop MPDU");
316 return it->second.second.erase(mpduIt);
322 return it->second.second.erase(mpduIt);
332 NS_LOG_DEBUG(
"Old packet. Remove from the EDCA queue, too");
336 return it->second.second.erase(mpduIt);
339 std::optional<PacketQueueI> prevIt;
340 if (mpduIt != it->second.second.begin())
342 prevIt = std::prev(mpduIt);
345 if (
m_queue->TtlExceeded(*mpduIt, now))
351 return (prevIt.has_value() ? std::next(prevIt.value()) : it->second.second.begin());
361 (*mpduIt)->GetHeader().SetRetry();
362 (*mpduIt)->ResetInFlight(linkId);
364 return it->second.second.erase(mpduIt);
371 NS_ASSERT(mpdu->GetHeader().IsQosData());
373 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
374 uint8_t tid = mpdu->GetHeader().GetQosTid();
378 NS_ASSERT(it->second.first.IsEstablished());
380 it->second.first.NotifyAckedMpdu(mpdu);
383 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end(); ++queueIt)
385 if ((*queueIt)->GetHeader().GetSequenceNumber() == mpdu->GetHeader().GetSequenceNumber())
387 m_queue->DequeueIfQueued({*queueIt});
398 NS_ASSERT(mpdu->GetHeader().IsQosData());
400 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
401 uint8_t tid = mpdu->GetHeader().GetQosTid();
405 NS_ASSERT(it->second.first.IsEstablished());
409 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end(); ++queueIt)
411 if ((*queueIt)->GetHeader().GetSequenceNumber() == mpdu->GetHeader().GetSequenceNumber())
419std::pair<uint16_t, uint16_t>
423 const std::set<uint8_t>& tids,
446 uint16_t nSuccessfulMpdus = 0;
447 uint16_t nFailedMpdus = 0;
449 if (it->second.first.m_inactivityEvent.IsPending())
454 it->second.first.m_inactivityEvent.Cancel();
456 it->second.first.m_inactivityEvent =
462 std::list<Ptr<const WifiMpdu>> acked;
464 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end();)
466 uint16_t currentSeq = (*queueIt)->GetHeader().GetSequenceNumber();
470 it->second.first.NotifyAckedMpdu(*queueIt);
476 acked.emplace_back(*queueIt);
486 m_queue->DequeueIfQueued(acked);
489 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end();)
493 auto linkIds = (*queueIt)->GetInFlightLinkIds();
495 if (linkIds.size() == 1 && *linkIds.begin() == linkId)
509 return {nSuccessfulMpdus, nFailedMpdus};
527 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
530 auto linkIds = (*mpduIt)->GetInFlightLinkIds();
531 if (!linkIds.contains(linkId))
545 if (!mpdu->GetHeader().IsQosData())
551 if (!mpdu->GetHeader().IsRetry() && !mpdu->IsInFlight())
557 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
558 uint8_t tid = mpdu->GetHeader().GetQosTid();
566 uint16_t currStartingSeq = it->second.first.GetStartingSequence();
574 it->second.first.NotifyDiscardedMpdu(mpdu);
578 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
580 if (it->second.first.GetDistance((*mpduIt)->GetHeader().GetSequenceNumber()) >=
584 m_queue->DequeueIfQueued({*mpduIt});
589 mpduIt = it->second.second.erase(mpduIt);
598 NS_LOG_DEBUG(
"Schedule a Block Ack Request for agreement (" << recipient <<
", " << +tid
604 hdr.
SetAddr2(mpdu->GetOriginal()->GetHeader().GetAddr2());
616 uint16_t startingSeq)
624 it->second.NotifyReceivedBar(startingSeq);
631 auto originator = mpdu->GetOriginal()->GetHeader().GetAddr2();
632 NS_ASSERT(mpdu->GetHeader().IsQosData());
633 auto tid = mpdu->GetHeader().GetQosTid();
640 it->second.NotifyReceivedMpdu(mpdu);
649 reqHdr.
SetType((*it).second.first.GetBlockAckReqType());
664 pkt->AddHeader(reqHdr);
668 while ((item =
m_queue->PeekByQueueId(queueId, item)))
670 if (item->GetHeader().IsBlockAckReq() && item->GetHeader().GetAddr1() == hdr.
GetAddr1())
673 item->GetPacket()->PeekHeader(otherHdr);
687const std::list<BlockAckManager::AgreementKey>&
726 if (!it->second.first.IsRejected())
743 if (!it->second.first.IsNoReply())
760 if (!it->second.first.IsReset())
791 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
796 if (mpduIt != it->second.second.begin())
852 size = it->second.first.GetBufferSize();
864 seqNum = it->second.first.GetStartingSequence();
uint16_t GetTimeout() const
Return the timeout.
void SetGcrGroupAddress(const Mac48Address &gcrGroupAddress)
Set the GCR group address for this agreement.
void SetImmediateBlockAck()
Set block ack policy to immediate Ack.
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
EventId m_inactivityEvent
inactivity event
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
void SetDelayedBlockAck()
Set block ack policy to delayed Ack.
void SetAmsduSupport(bool supported)
Enable or disable A-MSDU support.
void SetTimeout(uint16_t timeout)
Set timeout.
void SetHtSupported(bool htSupported)
Enable or disable HT support.
Manages all block ack agreements for an originator station.
void SetTxFailedCallback(TxFailed callback)
RecipientAgreementOptConstRef GetAgreementAsRecipient(const Mac48Address &originator, uint8_t tid) const
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
typedef for an iterator for Agreements
void SetQueue(const Ptr< WifiMacQueue > queue)
void DestroyRecipientAgreement(const Mac48Address &originator, uint8_t tid)
Destroy a recipient Block Ack agreement.
void SetTxOkCallback(TxOk callback)
void InactivityTimeout(const Mac48Address &recipient, uint8_t tid)
Inactivity timeout function.
uint8_t m_blockAckThreshold
block ack threshold
std::list< Ptr< WifiMpdu > > PacketQueue
typedef for a list of WifiMpdu.
RecipientAgreements m_recipientAgreements
Recipient Block Ack agreements.
~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
void SetDroppedOldMpduCallback(DroppedOldMpdu callback)
TxFailed m_txFailedCallback
transmit failed callback
void SetUnblockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
Set unblock destination callback.
std::optional< std::reference_wrapper< const OriginatorBlockAckAgreement > > OriginatorAgreementOptConstRef
optional const reference to OriginatorBlockAckAgreement
void NotifyOriginatorAgreementRejected(const Mac48Address &recipient, uint8_t tid)
Ptr< WifiMacQueue > m_queue
queue
uint16_t GetRecipientBufferSize(const Mac48Address &recipient, uint8_t tid) const
This function returns the buffer size negotiated with the recipient.
void CreateOriginatorAgreement(const MgtAddBaRequestHeader &reqHdr, const Mac48Address &recipient)
void CreateRecipientAgreement(const MgtAddBaResponseHeader &respHdr, const Mac48Address &originator, uint16_t startingSeq, Ptr< MacRxMiddle > rxMiddle)
void NotifyOriginatorAgreementNoReply(const Mac48Address &recipient, uint8_t tid)
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 NotifyOriginatorAgreementReset(const Mac48Address &recipient, uint8_t tid)
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)
void NotifyGotMpdu(Ptr< const WifiMpdu > mpdu)
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.
std::list< Ptr< WifiMpdu > >::iterator PacketQueueI
typedef for an iterator for PacketQueue.
std::list< AgreementKey > m_sendBarIfDataQueued
list of BA agreements for which a BAR shall only be sent if data is queued
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 > callback)
Set block ack inactivity callback.
uint16_t GetOriginatorStartingSequence(const Mac48Address &recipient, uint8_t tid) const
This function returns the starting sequence number of the transmit window.
Callback< void, Mac48Address, uint8_t, bool > m_blockAckInactivityTimeout
BlockAck inactivity timeout callback.
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.
std::optional< std::reference_wrapper< const RecipientBlockAckAgreement > > RecipientAgreementOptConstRef
optional const reference to RecipientBlockAckAgreement
void ScheduleBar(const CtrlBAckRequestHeader &reqHdr, const WifiMacHeader &hdr)
Callback< void, Mac48Address, uint8_t > m_blockPackets
block packets callback
void DestroyOriginatorAgreement(const Mac48Address &recipient, uint8_t tid)
OriginatorAgreementOptConstRef GetAgreementAsOriginator(const Mac48Address &recipient, uint8_t tid) const
CtrlBAckRequestHeader GetBlockAckReqHeader(const Mac48Address &recipient, uint8_t tid) const
const std::list< AgreementKey > & GetSendBarIfDataQueuedList() const
void NotifyGotBlockAckRequest(const Mac48Address &originator, uint8_t tid, uint16_t startingSeq)
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.
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...
void SetState(State state)
Set the current state.
void InitTxWindow()
Initialize the originator's transmit window by setting its size and starting sequence number equal to...
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...
void SetMacRxMiddle(const Ptr< MacRxMiddle > rxMiddle)
Set the MAC RX Middle to use.
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...