22 #include "ns3/simulator.h"
44 skipIfNoDataQueued (skipIfNoDataQueued)
56 .SetGroupName (
"Wifi")
58 .AddTraceSource (
"AgreementState",
59 "The state of the ADDBA handshake",
61 "ns3::BlockAckManager::AgreementStateTracedCallback")
97 it =
m_agreements.find (std::make_pair (recipient, tid));
103 return it->second.first.IsEstablished ();
105 return it->second.first.IsPending ();
107 return it->second.first.IsRejected ();
109 return it->second.first.IsNoReply ();
111 return it->second.first.IsReset ();
123 std::pair<Mac48Address, uint8_t> key (recipient, reqHdr->
GetTid ());
140 uint8_t tid = reqHdr->
GetTid ();
144 std::pair<OriginatorBlockAckAgreement, PacketQueue> value (agreement, queue);
164 for (std::list<Bar>::const_iterator i =
m_bars.begin (); i !=
m_bars.end (); )
166 if (i->bar->GetHeader ().GetAddr1 () == recipient && i->tid == tid)
180 uint16_t startingSeq)
183 uint8_t tid = respHdr->
GetTid ();
201 if (!it->second.first.IsEstablished ())
222 NS_ASSERT (mpdu->GetHeader ().IsQosData ());
224 uint8_t tid = mpdu->GetHeader ().GetQosTid ();
225 Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
230 uint16_t mpduDist = agreementIt->second.first.GetDistance (mpdu->GetHeader ().GetSequenceNumber ());
240 auto it = agreementIt->second.second.rbegin ();
241 while (it != agreementIt->second.second.rend ())
243 if (mpdu->GetHeader ().GetSequenceControl () == (*it)->GetHeader ().GetSequenceControl ())
245 NS_LOG_DEBUG (
"Packet already in the queue of the BA agreement");
249 uint16_t dist = agreementIt->second.first.GetDistance ((*it)->GetHeader ().GetSequenceNumber ());
251 if (mpduDist > dist ||
252 (mpduDist == dist && mpdu->GetHeader ().GetFragmentNumber () > (*it)->GetHeader ().GetFragmentNumber ()))
259 agreementIt->second.second.insert (it.base (), mpdu);
260 agreementIt->second.first.NotifyTransmittedMpdu (mpdu);
261 mpdu->SetInFlight ();
273 auto nextBar =
m_bars.begin ();
275 while (nextBar !=
m_bars.end ())
277 Mac48Address recipient = nextBar->bar->GetHeader ().GetAddr1 ();
280 && (!nextBar->bar->GetHeader ().IsBlockAckReq ()
281 ||
address != recipient || tid != nextBar->tid))
287 if (nextBar->bar->GetHeader ().IsBlockAckReq ())
293 nextBar =
m_bars.erase (nextBar);
296 if (nextBar->skipIfNoDataQueued
297 &&
m_queue->PeekByTidAndAddress (nextBar->tid, recipient) ==
nullptr)
304 for (
auto mpduIt = it->second.second.begin (); mpduIt != it->second.second.end (); )
306 if (!(*mpduIt)->IsQueued ())
309 mpduIt = it->second.second.erase (mpduIt);
313 if ((*mpduIt)->GetTimeStamp () +
m_queue->GetMaxDelay () <= now)
316 it->second.first.NotifyDiscardedMpdu (*mpduIt);
321 m_queue->TtlExceeded (*mpduIt, now);
322 mpduIt = it->second.second.erase (mpduIt);
332 nextBar->bar->GetPacket ()->PeekHeader (reqHdr);
338 nextBar->bar = Create<const WifiMacQueueItem> (packet, nextBar->bar->GetHeader ());
361 return it->second.second.size ();
377 if (!(*mpduIt)->IsQueued ())
381 NS_LOG_DEBUG (
"MPDU is not stored in the EDCA queue, drop MPDU");
382 return it->second.second.erase (mpduIt);
388 m_queue->DequeueIfQueued (*mpduIt);
389 return it->second.second.erase (mpduIt);
399 NS_LOG_DEBUG (
"Old packet. Remove from the EDCA queue, too");
404 m_queue->Remove (*mpduIt,
false);
405 return it->second.second.erase (mpduIt);
408 std::optional<PacketQueueI> prevIt;
409 if (mpduIt != it->second.second.begin ())
411 prevIt = std::prev (mpduIt);
414 if (
m_queue->TtlExceeded (*mpduIt, now))
420 return (prevIt.has_value () ? std::next (prevIt.value ()) : it->second.second.begin ());
430 (*mpduIt)->GetHeader ().SetRetry ();
431 (*mpduIt)->ResetInFlight ();
433 return it->second.second.erase (mpduIt);
440 NS_ASSERT (mpdu->GetHeader ().IsQosData ());
442 Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
443 uint8_t tid = mpdu->GetHeader ().GetQosTid ();
449 it->second.first.NotifyAckedMpdu (mpdu);
452 for (
auto queueIt = it->second.second.begin (); queueIt != it->second.second.end (); ++queueIt)
454 if ((*queueIt)->GetHeader ().GetSequenceNumber () == mpdu->GetHeader ().GetSequenceNumber ())
466 NS_ASSERT (mpdu->GetHeader ().IsQosData ());
468 Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
469 uint8_t tid = mpdu->GetHeader ().GetQosTid ();
477 for (
auto queueIt = it->second.second.begin (); queueIt != it->second.second.end (); ++queueIt)
479 if ((*queueIt)->GetHeader ().GetSequenceNumber () == mpdu->GetHeader ().GetSequenceNumber ())
487 std::pair<uint16_t,uint16_t>
489 const std::set<uint8_t>& tids,
size_t index)
492 uint16_t nSuccessfulMpdus = 0;
493 uint16_t nFailedMpdus = 0;
504 tid = *tids.begin ();
510 if (it->second.first.m_inactivityEvent.IsRunning ())
515 it->second.first.m_inactivityEvent.Cancel ();
526 for (
auto queueIt = it->second.second.begin (); queueIt != it->second.second.end (); )
528 uint16_t currentSeq = (*queueIt)->GetHeader ().GetSequenceNumber ();
531 it->second.first.NotifyAckedMpdu (*queueIt);
550 return {nSuccessfulMpdus, nFailedMpdus};
564 for (
auto mpduIt = it->second.second.begin (); mpduIt != it->second.second.end (); )
576 if (!mpdu->GetHeader ().IsQosData ())
582 if (!mpdu->GetHeader ().IsRetry () && !mpdu->IsInFlight ())
588 Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
589 uint8_t tid = mpdu->GetHeader ().GetQosTid ();
597 uint16_t currStartingSeq = it->second.first.GetStartingSequence ();
605 it->second.first.NotifyDiscardedMpdu (mpdu);
609 for (
auto mpduIt = it->second.second.begin (); mpduIt != it->second.second.end (); )
611 if (it->second.first.GetDistance ((*mpduIt)->GetHeader ().GetSequenceNumber ()) >=
SEQNO_SPACE_HALF_SIZE)
614 m_queue->DequeueIfQueued (*mpduIt);
619 mpduIt = it->second.second.erase (mpduIt);
628 NS_LOG_DEBUG (
"Schedule a Block Ack Request for agreement (" << recipient <<
", " << +tid <<
")");
635 hdr.
SetAddr2 (mpdu->GetHeader ().GetAddr2 ());
636 hdr.
SetAddr3 (mpdu->GetHeader ().GetAddr3 ());
642 ScheduleBar (Create<const WifiMacQueueItem> (bar, hdr));
653 reqHdr.
SetType ((*it).second.first.GetBlockAckReqType ());
663 NS_ASSERT (bar->GetHeader ().IsBlockAckReq () || bar->GetHeader ().IsTrigger ());
666 if (bar->GetHeader ().IsBlockAckReq ())
669 bar->GetPacket ()->PeekHeader (reqHdr);
672 #ifdef NS3_BUILD_PROFILE_DEBUG
676 bar->GetPacket ()->PeekHeader (triggerHdr);
680 Bar request (bar, tid, skipIfNoDataQueued);
683 std::list<Bar>::const_iterator i =
m_bars.end ();
685 if (bar->GetHeader ().IsBlockAckReq ())
689 if (i->bar->GetHeader ().IsBlockAckReq ()
690 && i->bar->GetHeader ().GetAddr1 () == bar->GetHeader ().GetAddr1 () && i->tid == tid)
698 if (bar->GetHeader ().IsRetry ())
700 m_bars.push_front (request);
704 m_bars.insert (i, request);
721 if (!it->second.first.IsEstablished ())
726 it->second.first.SetStartingSequence (startingSeq);
735 if (!it->second.first.IsRejected ())
748 if (!it->second.first.IsNoReply ())
762 if (!it->second.first.IsReset ())
783 uint32_t packets =
m_queue->GetNPacketsByTidAndAddress (tid, recipient) +
804 for (
auto mpduIt = it->second.second.begin (); mpduIt != it->second.second.end (); )
809 if (mpduIt != it->second.second.begin ())
868 size = it->second.first.GetBufferSize ();
878 return it->second.first.GetBlockAckReqType ();
886 return it->second.first.GetBlockAckType ();
896 seqNum = it->second.first.GetStartingSequence ();
void SetImmediateBlockAck(void)
Set block ack policy to immediate Ack.
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
void SetDelayedBlockAck(void)
Set block ack policy to delayed Ack.
uint16_t GetTimeout(void) const
Return the timeout.
EventId m_inactivityEvent
inactivity event
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
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 StorePacket(Ptr< WifiMacQueueItem > mpdu)
std::list< Ptr< WifiMacQueueItem > >::iterator PacketQueueI
typedef for an iterator for PacketQueue.
void ScheduleBar(Ptr< const WifiMacQueueItem > bar, bool skipIfNoDataQueued=false)
void SetTxFailedCallback(TxFailed callback)
void NotifyAgreementRejected(Mac48Address recipient, uint8_t tid)
CtrlBAckRequestHeader GetBlockAckReqHeader(Mac48Address recipient, uint8_t tid) const
Callback< void, Mac48Address, uint8_t > m_unblockPackets
unblock packets callback
void SetQueue(const Ptr< WifiMacQueue > queue)
void SetTxOkCallback(TxOk callback)
bool SwitchToBlockAckIfNeeded(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
uint8_t m_blockAckThreshold
block ack threshold
void SetBlockAckThreshold(uint8_t nPackets)
DroppedOldMpdu m_droppedOldMpduCallback
the dropped MPDU callback
std::list< Ptr< WifiMacQueueItem > > PacketQueue
typedef for a list of WifiMacQueueItem.
void NotifyAgreementEstablished(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
void SetDroppedOldMpduCallback(DroppedOldMpdu callback)
void DestroyAgreement(Mac48Address recipient, uint8_t tid)
void NotifyDiscardedMpdu(Ptr< const WifiMacQueueItem > mpdu)
void NotifyGotAck(Ptr< const WifiMacQueueItem > mpdu)
Invoked upon receipt of an Ack frame after the transmission of a QoS data frame sent under an establi...
TxFailed m_txFailedCallback
transmit failed callback
void SetUnblockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
Set unblock destination callback.
Ptr< WifiMacQueue > m_queue
queue
std::pair< uint16_t, uint16_t > NotifyGotBlockAck(const CtrlBAckResponseHeader &blockAck, Mac48Address recipient, const std::set< uint8_t > &tids, size_t index=0)
BlockAckReqType GetBlockAckReqType(Mac48Address recipient, uint8_t tid) const
This function returns the type of Block Acks sent to the recipient.
void NotifyAgreementReset(Mac48Address recipient, uint8_t tid)
void NotifyMissedAck(Ptr< WifiMacQueueItem > mpdu)
Invoked upon missed reception of an Ack frame after the transmission of a QoS data frame sent under a...
TracedCallback< Time, Mac48Address, uint8_t, OriginatorBlockAckAgreement::State > m_agreementState
The trace source fired when a state transition occurred.
std::map< std::pair< Mac48Address, uint8_t >, std::pair< OriginatorBlockAckAgreement, PacketQueue > >::const_iterator AgreementsCI
typedef for a const iterator for Agreements.
void UpdateAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address recipient, uint16_t startingSeq)
Ptr< const WifiMacQueueItem > GetBar(bool remove=true, uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast())
Returns the next BlockAckRequest or MU-BAR Trigger Frame to send, if any.
uint16_t GetRecipientBufferSize(Mac48Address recipient, uint8_t tid) const
This function returns the buffer size negotiated with the recipient.
void InactivityTimeout(Mac48Address recipient, uint8_t tid)
Inactivity timeout function.
bool ExistsAgreement(Mac48Address recipient, uint8_t tid) const
void NotifyAgreementNoReply(Mac48Address recipient, uint8_t tid)
bool NeedBarRetransmission(uint8_t tid, Mac48Address recipient)
This function returns true if a block ack agreement is established with the given recipient for the g...
BlockAckType GetBlockAckType(Mac48Address recipient, uint8_t tid) const
This function returns the type of Block Acks sent by the recipient.
static TypeId GetTypeId(void)
Get the type ID.
Agreements m_agreements
This data structure contains, for each block ack agreement (recipient, TID), a set of packets for whi...
void CreateAgreement(const MgtAddBaRequestHeader *reqHdr, Mac48Address recipient, bool htSupported=true)
void SetBlockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
Set block destination callback.
void SetBlockAckInactivityCallback(Callback< void, Mac48Address, uint8_t, bool > callback)
Set block ack inactivity callback.
bool ExistsAgreementInState(Mac48Address recipient, uint8_t tid, OriginatorBlockAckAgreement::State state) const
Callback< void, Mac48Address, uint8_t, bool > m_blockAckInactivityTimeout
BlockAck inactivity timeout callback.
std::map< std::pair< Mac48Address, uint8_t >, std::pair< OriginatorBlockAckAgreement, PacketQueue > >::iterator AgreementsI
typedef for an iterator for Agreements.
TxOk m_txOkCallback
transmit OK callback
MpduStatus
Enumeration for the statuses of a buffered MPDU.
void NotifyMissedBlockAck(Mac48Address recipient, uint8_t tid)
void DoDispose() override
Destructor implementation.
uint32_t GetNBufferedPackets(Mac48Address recipient, uint8_t tid) const
Callback< void, Mac48Address, uint8_t > m_blockPackets
block packets callback
uint16_t GetOriginatorStartingSequence(Mac48Address recipient, uint8_t tid) const
This function returns the starting sequence number of the transmit window.
std::list< Bar > m_bars
list of BARs
PacketQueueI HandleInFlightMpdu(PacketQueueI mpduIt, MpduStatus status, const AgreementsI &it, const Time &now)
Handle the given in flight MPDU based on its given status.
bool IsNull(void) const
Check for null implementation.
static Mac48Address GetBroadcast(void)
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 InitTxWindow(void)
Initialize the originator's transmit window by setting its size and starting sequence number equal to...
void SetState(State state)
Set the current state.
State
Represents the state for this agreement.
void AddHeader(const Header &header)
Add header to this packet.
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now(void)
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_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#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.
const uint16_t SEQNO_SPACE_HALF_SIZE
Size of the half the space of sequence numbers (used to determine old packets)
BlockAckRequest frame information.
uint8_t tid
TID (unused if MU-BAR)
bool skipIfNoDataQueued
do not send if there is no data queued (unused if MU-BAR)
Ptr< const WifiMacQueueItem > bar
BlockAckRequest or MU-BAR Trigger Frame.
The different BlockAckRequest variants.
The different BlockAck variants.