20#include "ns3/simulator.h"
36 TypeId(
"ns3::BlockAckManager")
40 .AddTraceSource(
"AgreementState",
41 "The state of the ADDBA handshake",
43 "ns3::BlockAckManager::AgreementStateTracedCallback");
71 return std::cref(it->second.first);
83 return std::cref(it->second);
94 const auto tid = reqHdr.
GetTid();
120 "Existing agreement must be in RESET state");
123 std::make_pair(std::move(agreement),
PacketQueue{}));
141 uint16_t startingSeq)
144 uint8_t tid = respHdr.
GetTid();
162 if (!it->second.first.IsEstablished())
186 uint16_t startingSeq,
189 NS_LOG_FUNCTION(
this << respHdr << originator << startingSeq << rxMiddle);
190 const auto tid = respHdr.
GetTid();
222 agreementIt->second.Flush();
231 NS_ASSERT(mpdu->GetHeader().IsQosData());
233 uint8_t tid = mpdu->GetHeader().GetQosTid();
240 agreementIt->second.first.GetDistance(mpdu->GetHeader().GetSequenceNumber());
250 auto it = agreementIt->second.second.rbegin();
251 while (it != agreementIt->second.second.rend())
253 if (mpdu->GetHeader().GetSequenceControl() == (*it)->GetHeader().GetSequenceControl())
255 NS_LOG_DEBUG(
"Packet already in the queue of the BA agreement");
260 agreementIt->second.first.GetDistance((*it)->GetHeader().GetSequenceNumber());
262 if (mpduDist > dist || (mpduDist == dist && mpdu->GetHeader().GetFragmentNumber() >
263 (*it)->GetHeader().GetFragmentNumber()))
270 agreementIt->second.second.insert(it.base(), mpdu);
271 agreementIt->second.first.NotifyTransmittedMpdu(mpdu);
283 return it->second.second.size();
300 NS_LOG_FUNCTION(
this << linkId << **mpduIt << +
static_cast<uint8_t
>(status));
302 if (!(*mpduIt)->IsQueued())
306 NS_LOG_DEBUG(
"MPDU is not stored in the EDCA queue, drop MPDU");
307 return it->second.second.erase(mpduIt);
313 return it->second.second.erase(mpduIt);
323 NS_LOG_DEBUG(
"Old packet. Remove from the EDCA queue, too");
327 return it->second.second.erase(mpduIt);
330 std::optional<PacketQueueI> prevIt;
331 if (mpduIt != it->second.second.begin())
333 prevIt = std::prev(mpduIt);
336 if (
m_queue->TtlExceeded(*mpduIt, now))
342 return (prevIt.has_value() ? std::next(prevIt.value()) : it->second.second.begin());
352 (*mpduIt)->GetHeader().SetRetry();
353 (*mpduIt)->ResetInFlight(linkId);
355 return it->second.second.erase(mpduIt);
362 NS_ASSERT(mpdu->GetHeader().IsQosData());
364 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
365 uint8_t tid = mpdu->GetHeader().GetQosTid();
369 NS_ASSERT(it->second.first.IsEstablished());
371 it->second.first.NotifyAckedMpdu(mpdu);
374 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end(); ++queueIt)
376 if ((*queueIt)->GetHeader().GetSequenceNumber() == mpdu->GetHeader().GetSequenceNumber())
378 m_queue->DequeueIfQueued({*queueIt});
389 NS_ASSERT(mpdu->GetHeader().IsQosData());
391 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
392 uint8_t tid = mpdu->GetHeader().GetQosTid();
396 NS_ASSERT(it->second.first.IsEstablished());
400 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end(); ++queueIt)
402 if ((*queueIt)->GetHeader().GetSequenceNumber() == mpdu->GetHeader().GetSequenceNumber())
410std::pair<uint16_t, uint16_t>
414 const std::set<uint8_t>& tids,
437 uint16_t nSuccessfulMpdus = 0;
438 uint16_t nFailedMpdus = 0;
440 if (it->second.first.m_inactivityEvent.IsPending())
445 it->second.first.m_inactivityEvent.Cancel();
447 it->second.first.m_inactivityEvent =
453 std::list<Ptr<const WifiMpdu>> acked;
455 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end();)
457 uint16_t currentSeq = (*queueIt)->GetHeader().GetSequenceNumber();
461 it->second.first.NotifyAckedMpdu(*queueIt);
467 acked.emplace_back(*queueIt);
477 m_queue->DequeueIfQueued(acked);
480 for (
auto queueIt = it->second.second.begin(); queueIt != it->second.second.end();)
484 auto linkIds = (*queueIt)->GetInFlightLinkIds();
486 if (linkIds.size() == 1 && *linkIds.begin() == linkId)
500 return {nSuccessfulMpdus, nFailedMpdus};
518 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
521 auto linkIds = (*mpduIt)->GetInFlightLinkIds();
522 if (!linkIds.contains(linkId))
536 if (!mpdu->GetHeader().IsQosData())
542 if (!mpdu->GetHeader().IsRetry() && !mpdu->IsInFlight())
548 Mac48Address recipient = mpdu->GetOriginal()->GetHeader().GetAddr1();
549 uint8_t tid = mpdu->GetHeader().GetQosTid();
557 uint16_t currStartingSeq = it->second.first.GetStartingSequence();
565 it->second.first.NotifyDiscardedMpdu(mpdu);
569 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
571 if (it->second.first.GetDistance((*mpduIt)->GetHeader().GetSequenceNumber()) >=
575 m_queue->DequeueIfQueued({*mpduIt});
580 mpduIt = it->second.second.erase(mpduIt);
589 NS_LOG_DEBUG(
"Schedule a Block Ack Request for agreement (" << recipient <<
", " << +tid
595 hdr.
SetAddr2(mpdu->GetOriginal()->GetHeader().GetAddr2());
607 uint16_t startingSeq)
615 it->second.NotifyReceivedBar(startingSeq);
622 auto originator = mpdu->GetOriginal()->GetHeader().GetAddr2();
623 NS_ASSERT(mpdu->GetHeader().IsQosData());
624 auto tid = mpdu->GetHeader().GetQosTid();
631 it->second.NotifyReceivedMpdu(mpdu);
642 reqHdr.
SetType((*it).second.first.GetBlockAckReqType());
657 pkt->AddHeader(reqHdr);
661 while ((item =
m_queue->PeekByQueueId(queueId, item)))
663 if (item->GetHeader().IsBlockAckReq() && item->GetHeader().GetAddr1() == hdr.
GetAddr1())
666 item->GetPacket()->PeekHeader(otherHdr);
680const std::list<BlockAckManager::AgreementKey>&
716 uint16_t startingSeq)
721 if (!it->second.first.IsEstablished())
729 it->second.first.SetStartingSequence(startingSeq);
738 if (!it->second.first.IsRejected())
755 if (!it->second.first.IsNoReply())
772 if (!it->second.first.IsReset())
803 for (
auto mpduIt = it->second.second.begin(); mpduIt != it->second.second.end();)
808 if (mpduIt != it->second.second.begin())
864 size = it->second.first.GetBufferSize();
876 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)
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...