31#include "ns3/simulator.h"
46 TypeId(
"ns3::BlockAckManager")
50 .AddTraceSource(
"AgreementState",
51 "The state of the ADDBA handshake",
53 "ns3::BlockAckManager::AgreementStateTracedCallback");
81 return std::cref(it->second.first);
93 return std::cref(it->second);
105 const uint8_t tid = reqHdr.
GetTid();
130 "Existing agreement must be in RESET state");
133 std::make_pair(std::move(agreement),
PacketQueue{}));
151 uint16_t startingSeq)
154 uint8_t tid = respHdr.
GetTid();
172 if (!it->second.first.IsEstablished())
196 uint16_t startingSeq,
200 NS_LOG_FUNCTION(
this << respHdr << originator << startingSeq << htSupported << rxMiddle);
201 uint8_t 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);
293 return it->second.second.size();
310 NS_LOG_FUNCTION(
this << linkId << **mpduIt << +
static_cast<uint8_t
>(status));
312 if (!(*mpduIt)->IsQueued())
316 NS_LOG_DEBUG(
"MPDU is not stored in the EDCA queue, drop MPDU");
317 return it->second.second.erase(mpduIt);
323 return it->second.second.erase(mpduIt);
333 NS_LOG_DEBUG(
"Old packet. Remove from the EDCA queue, too");
339 return it->second.second.erase(mpduIt);
342 std::optional<PacketQueueI> prevIt;
343 if (mpduIt != it->second.second.begin())
345 prevIt = std::prev(mpduIt);
348 if (
m_queue->TtlExceeded(*mpduIt, now))
354 return (prevIt.has_value() ? std::next(prevIt.value()) : it->second.second.begin());
364 (*mpduIt)->GetHeader().SetRetry();
365 (*mpduIt)->ResetInFlight(linkId);
367 return it->second.second.erase(mpduIt);
374 NS_ASSERT(mpdu->GetHeader().IsQosData());
376 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
377 uint8_t tid = mpdu->GetHeader().GetQosTid();
381 NS_ASSERT(it->second.first.IsEstablished());
383 it->second.first.NotifyAckedMpdu(mpdu);
386 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end(); ++queueIt)
388 if ((*queueIt)->GetHeader().GetSequenceNumber() == mpdu->GetHeader().GetSequenceNumber())
390 m_queue->DequeueIfQueued({*queueIt});
401 NS_ASSERT(mpdu->GetHeader().IsQosData());
403 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
404 uint8_t tid = mpdu->GetHeader().GetQosTid();
408 NS_ASSERT(it->second.first.IsEstablished());
412 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end(); ++queueIt)
414 if ((*queueIt)->GetHeader().GetSequenceNumber() == mpdu->GetHeader().GetSequenceNumber())
422std::pair<uint16_t, uint16_t>
426 const std::set<uint8_t>& tids,
449 uint16_t nSuccessfulMpdus = 0;
450 uint16_t nFailedMpdus = 0;
452 if (it->second.first.m_inactivityEvent.IsRunning())
457 it->second.first.m_inactivityEvent.Cancel();
459 it->second.first.m_inactivityEvent =
465 std::list<Ptr<const WifiMpdu>> acked;
467 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end();)
469 uint16_t currentSeq = (*queueIt)->GetHeader().GetSequenceNumber();
473 it->second.first.NotifyAckedMpdu(*queueIt);
479 acked.emplace_back(*queueIt);
489 m_queue->DequeueIfQueued(acked);
492 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end();)
496 auto linkIds = (*queueIt)->GetInFlightLinkIds();
498 if (linkIds.size() == 1 && *linkIds.begin() == linkId)
512 return {nSuccessfulMpdus, nFailedMpdus};
530 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
533 auto linkIds = (*mpduIt)->GetInFlightLinkIds();
534 if (linkIds.count(linkId) == 0)
548 if (!mpdu->GetHeader().IsQosData())
554 if (!mpdu->GetHeader().IsRetry() && !mpdu->IsInFlight())
560 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
561 uint8_t tid = mpdu->GetHeader().GetQosTid();
569 uint16_t currStartingSeq = it->second.first.GetStartingSequence();
577 it->second.first.NotifyDiscardedMpdu(mpdu);
581 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
583 if (it->second.first.GetDistance((*mpduIt)->GetHeader().GetSequenceNumber()) >=
587 m_queue->DequeueIfQueued({*mpduIt});
592 mpduIt = it->second.second.erase(mpduIt);
601 NS_LOG_DEBUG(
"Schedule a Block Ack Request for agreement (" << recipient <<
", " << +tid
607 hdr.
SetAddr2(mpdu->GetOriginal()->GetHeader().GetAddr2());
619 uint16_t startingSeq)
627 it->second.NotifyReceivedBar(startingSeq);
634 auto originator = mpdu->GetOriginal()->GetHeader().GetAddr2();
635 NS_ASSERT(mpdu->GetHeader().IsQosData());
636 auto tid = mpdu->GetHeader().GetQosTid();
643 it->second.NotifyReceivedMpdu(mpdu);
654 reqHdr.
SetType((*it).second.first.GetBlockAckReqType());
668 auto pkt = Create<Packet>();
669 pkt->AddHeader(reqHdr);
673 while ((item =
m_queue->PeekByQueueId(queueId, item)))
675 if (item->GetHeader().IsBlockAckReq() && item->GetHeader().GetAddr1() == hdr.
GetAddr1())
678 item->GetPacket()->PeekHeader(otherHdr);
681 auto bar = Create<WifiMpdu>(pkt, hdr, item->GetTimestamp());
689 m_queue->Enqueue(Create<WifiMpdu>(pkt, hdr));
696 NS_ASSERT(muBar->GetHeader().IsTrigger());
698#ifdef NS3_BUILD_PROFILE_DEBUG
700 muBar->GetPacket()->PeekHeader(triggerHdr);
707const std::list<BlockAckManager::AgreementKey>&
743 uint16_t startingSeq)
748 if (!it->second.first.IsEstablished())
756 it->second.first.SetStartingSequence(startingSeq);
765 if (!it->second.first.IsRejected())
781 if (!it->second.first.IsNoReply())
798 if (!it->second.first.IsReset())
829 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
834 if (mpduIt != it->second.second.begin())
890 size = it->second.first.GetBufferSize();
902 seqNum = it->second.first.GetStartingSequence();
uint16_t GetTimeout() const
Return the timeout.
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
void NotifyOriginatorAgreementEstablished(const Mac48Address &recipient, uint8_t tid, uint16_t startingSeq)
void CreateOriginatorAgreement(const MgtAddBaRequestHeader &reqHdr, const Mac48Address &recipient, bool htSupported=true)
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.
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)
TxFailed m_txFailedCallback
transmit failed callback
void SetUnblockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
Set unblock destination callback.
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 CreateRecipientAgreement(const MgtAddBaResponseHeader &respHdr, const Mac48Address &originator, uint16_t startingSeq, bool htSupported, Ptr< MacRxMiddle > rxMiddle)
void ScheduleMuBar(Ptr< WifiMpdu > muBar)
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.
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.
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...