31 #include "ns3/simulator.h"
47 TypeId(
"ns3::BlockAckManager")
51 .AddTraceSource(
"AgreementState",
52 "The state of the ADDBA handshake",
54 "ns3::BlockAckManager::AgreementStateTracedCallback");
82 return std::cref(it->second.first);
94 return std::cref(it->second);
106 const uint8_t tid = reqHdr.
GetTid();
131 "Existing agreement must be in RESET state");
134 std::make_pair(std::move(agreement),
PacketQueue{}));
152 uint16_t startingSeq)
155 uint8_t tid = respHdr.
GetTid();
173 if (!it->second.first.IsEstablished())
197 uint16_t startingSeq,
201 NS_LOG_FUNCTION(
this << respHdr << originator << startingSeq << htSupported << rxMiddle);
202 uint8_t tid = respHdr.
GetTid();
233 agreementIt->second.Flush();
242 NS_ASSERT(mpdu->GetHeader().IsQosData());
244 uint8_t tid = mpdu->GetHeader().GetQosTid();
251 agreementIt->second.first.GetDistance(mpdu->GetHeader().GetSequenceNumber());
261 auto it = agreementIt->second.second.rbegin();
262 while (it != agreementIt->second.second.rend())
264 if (mpdu->GetHeader().GetSequenceControl() == (*it)->GetHeader().GetSequenceControl())
266 NS_LOG_DEBUG(
"Packet already in the queue of the BA agreement");
271 agreementIt->second.first.GetDistance((*it)->GetHeader().GetSequenceNumber());
273 if (mpduDist > dist || (mpduDist == dist && mpdu->GetHeader().GetFragmentNumber() >
274 (*it)->GetHeader().GetFragmentNumber()))
281 agreementIt->second.second.insert(it.base(), mpdu);
282 agreementIt->second.first.NotifyTransmittedMpdu(mpdu);
294 return it->second.second.size();
311 NS_LOG_FUNCTION(
this << linkId << **mpduIt << +
static_cast<uint8_t
>(status));
313 if (!(*mpduIt)->IsQueued())
317 NS_LOG_DEBUG(
"MPDU is not stored in the EDCA queue, drop MPDU");
318 return it->second.second.erase(mpduIt);
324 return it->second.second.erase(mpduIt);
334 NS_LOG_DEBUG(
"Old packet. Remove from the EDCA queue, too");
340 return it->second.second.erase(mpduIt);
343 std::optional<PacketQueueI> prevIt;
344 if (mpduIt != it->second.second.begin())
349 if (
m_queue->TtlExceeded(*mpduIt, now))
355 return (prevIt.has_value() ? std::next(prevIt.value()) : it->second.second.begin());
365 (*mpduIt)->GetHeader().SetRetry();
366 (*mpduIt)->ResetInFlight(linkId);
368 return it->second.second.erase(mpduIt);
375 NS_ASSERT(mpdu->GetHeader().IsQosData());
377 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
378 uint8_t tid = mpdu->GetHeader().GetQosTid();
382 NS_ASSERT(it->second.first.IsEstablished());
384 it->second.first.NotifyAckedMpdu(mpdu);
387 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end(); ++queueIt)
389 if ((*queueIt)->GetHeader().GetSequenceNumber() == mpdu->GetHeader().GetSequenceNumber())
391 m_queue->DequeueIfQueued({*queueIt});
402 NS_ASSERT(mpdu->GetHeader().IsQosData());
404 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
405 uint8_t tid = mpdu->GetHeader().GetQosTid();
409 NS_ASSERT(it->second.first.IsEstablished());
413 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end(); ++queueIt)
415 if ((*queueIt)->GetHeader().GetSequenceNumber() == mpdu->GetHeader().GetSequenceNumber())
423 std::pair<uint16_t, uint16_t>
427 const std::set<uint8_t>& tids,
450 uint16_t nSuccessfulMpdus = 0;
451 uint16_t nFailedMpdus = 0;
453 if (it->second.first.m_inactivityEvent.IsRunning())
458 it->second.first.m_inactivityEvent.Cancel();
460 it->second.first.m_inactivityEvent =
466 std::list<Ptr<const WifiMpdu>> acked;
468 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end();)
470 uint16_t currentSeq = (*queueIt)->GetHeader().GetSequenceNumber();
474 it->second.first.NotifyAckedMpdu(*queueIt);
480 acked.emplace_back(*queueIt);
490 m_queue->DequeueIfQueued(acked);
493 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end();)
497 auto linkIds = (*queueIt)->GetInFlightLinkIds();
499 if (linkIds.size() == 1 && *linkIds.begin() == linkId)
513 return {nSuccessfulMpdus, nFailedMpdus};
531 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
534 auto linkIds = (*mpduIt)->GetInFlightLinkIds();
535 if (linkIds.count(linkId) == 0)
549 if (!mpdu->GetHeader().IsQosData())
555 if (!mpdu->GetHeader().IsRetry() && !mpdu->IsInFlight())
561 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
562 uint8_t tid = mpdu->GetHeader().GetQosTid();
570 uint16_t currStartingSeq = it->second.first.GetStartingSequence();
578 it->second.first.NotifyDiscardedMpdu(mpdu);
582 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
584 if (it->second.first.GetDistance((*mpduIt)->GetHeader().GetSequenceNumber()) >=
588 m_queue->DequeueIfQueued({*mpduIt});
593 mpduIt = it->second.second.erase(mpduIt);
602 NS_LOG_DEBUG(
"Schedule a Block Ack Request for agreement (" << recipient <<
", " << +tid
608 hdr.
SetAddr2(mpdu->GetOriginal()->GetHeader().GetAddr2());
620 uint16_t startingSeq)
628 it->second.NotifyReceivedBar(startingSeq);
635 auto originator = mpdu->GetOriginal()->GetHeader().GetAddr2();
636 NS_ASSERT(mpdu->GetHeader().IsQosData());
637 auto tid = mpdu->GetHeader().GetQosTid();
644 it->second.NotifyReceivedMpdu(mpdu);
655 reqHdr.
SetType((*it).second.first.GetBlockAckReqType());
669 auto pkt = Create<Packet>();
670 pkt->AddHeader(reqHdr);
674 while ((item =
m_queue->PeekByQueueId(queueId, item)))
676 if (item->GetHeader().IsBlockAckReq() && item->GetHeader().GetAddr1() == hdr.
GetAddr1())
679 item->GetPacket()->PeekHeader(otherHdr);
682 auto bar = Create<WifiMpdu>(pkt, hdr, item->GetTimestamp());
690 m_queue->Enqueue(Create<WifiMpdu>(pkt, hdr));
693 const std::list<BlockAckManager::AgreementKey>&
729 uint16_t startingSeq)
734 if (!it->second.first.IsEstablished())
742 it->second.first.SetStartingSequence(startingSeq);
751 if (!it->second.first.IsRejected())
768 if (!it->second.first.IsNoReply())
785 if (!it->second.first.IsReset())
816 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
821 if (mpduIt != it->second.second.begin())
877 size = it->second.first.GetBufferSize();
889 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 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< AgreementKey > m_sendBarIfDataQueued
list of BA agreements for which a BAR shall only be sent if data is queued
std::list< Ptr< WifiMpdu > >::iterator PacketQueueI
typedef for an iterator for PacketQueue.
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...