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")
93 it =
m_agreements.find (std::make_pair (recipient, tid));
99 return it->second.first.IsEstablished ();
101 return it->second.first.IsPending ();
103 return it->second.first.IsRejected ();
105 return it->second.first.IsNoReply ();
107 return it->second.first.IsReset ();
119 std::pair<Mac48Address, uint8_t> key (recipient, reqHdr->
GetTid ());
130 agreement.SetImmediateBlockAck ();
134 agreement.SetDelayedBlockAck ();
136 uint8_t tid = reqHdr->
GetTid ();
140 std::pair<OriginatorBlockAckAgreement, PacketQueue> value (agreement, queue);
160 if ((*i)->GetHeader ().GetAddr1 () == recipient && (*i)->GetHeader ().GetQosTid () == tid)
171 for (std::list<Bar>::const_iterator i =
m_bars.begin (); i !=
m_bars.end (); )
173 if (i->bar->GetHeader ().GetAddr1 () == recipient && i->tid == tid)
189 uint8_t tid = respHdr->
GetTid ();
203 WifiMacQueue::ConstIterator mpduIt =
m_retryPackets->PeekByTidAndAddress (tid, recipient);
206 startSeq = (*mpduIt)->GetHeader ().GetSequenceNumber ();
210 startSeq =
m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient);
222 if (!it->second.first.IsEstablished ())
249 NS_ASSERT (mpdu->GetHeader ().IsQosData ());
251 uint8_t tid = mpdu->GetHeader ().GetQosTid ();
252 Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
257 uint16_t mpduDist = agreementIt->second.first.GetDistance (mpdu->GetHeader ().GetSequenceNumber ());
268 while (it != agreementIt->second.second.end ())
270 if (mpdu->GetHeader ().GetSequenceControl () == (*it)->GetHeader ().GetSequenceControl ())
272 NS_LOG_DEBUG (
"Packet already in the queue of the BA agreement");
276 uint16_t dist = agreementIt->second.first.GetDistance ((*it)->GetHeader ().GetSequenceNumber ());
278 if (mpduDist < dist ||
279 (mpduDist == dist && mpdu->GetHeader ().GetFragmentNumber () < (*it)->GetHeader ().GetFragmentNumber ()))
286 agreementIt->second.second.insert (it, mpdu);
287 agreementIt->second.first.NotifyTransmittedMpdu (mpdu);
298 auto nextBar =
m_bars.begin ();
300 while (nextBar !=
m_bars.end ())
302 if (nextBar->bar->GetHeader ().IsBlockAckReq ())
304 Mac48Address recipient = nextBar->bar->GetHeader ().GetAddr1 ();
309 nextBar =
m_bars.erase (nextBar);
312 if (nextBar->skipIfNoDataQueued
314 &&
m_queue->PeekByTidAndAddress (nextBar->tid, recipient) ==
m_queue->end ())
321 for (
auto mpduIt = it->second.second.begin (); mpduIt != it->second.second.end (); )
326 it->second.first.NotifyDiscardedMpdu (*mpduIt);
327 mpduIt = it->second.second.erase (mpduIt);
336 nextBar->bar->GetPacket ()->PeekHeader (reqHdr);
342 nextBar->bar = Create<const WifiMacQueueItem> (packet, nextBar->bar->GetHeader ());
372 uint32_t nPackets = 0;
374 while (queueIt != (*it).second.second.end ())
376 uint16_t currentSeq = (*queueIt)->GetHeader ().GetSequenceNumber ();
379 while (queueIt != (*it).second.second.end () && (*queueIt)->GetHeader ().GetSequenceNumber () == currentSeq)
405 NS_ASSERT (mpdu->GetHeader ().IsQosData ());
407 Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
408 uint8_t tid = mpdu->GetHeader ().GetQosTid ();
416 while (queueIt != it->second.second.end ())
418 if ((*queueIt)->GetHeader ().GetSequenceNumber () == mpdu->GetHeader ().GetSequenceNumber ())
420 queueIt = it->second.second.erase (queueIt);
428 it->second.first.NotifyAckedMpdu (mpdu);
435 NS_ASSERT (mpdu->GetHeader ().IsQosData ());
437 Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
438 uint8_t tid = mpdu->GetHeader ().GetQosTid ();
447 while (queueIt != it->second.second.end ())
449 if ((*queueIt)->GetHeader ().GetSequenceNumber () == mpdu->GetHeader ().GetSequenceNumber ())
451 queueIt = it->second.second.erase (queueIt);
466 NS_LOG_FUNCTION (
this << blockAck << recipient << rxSnr << dataSnr << dataTxVector);
472 bool foundFirstLost =
false;
473 uint8_t nSuccessfulMpdus = 0;
474 uint8_t nFailedMpdus = 0;
478 if (it->second.first.m_inactivityEvent.IsRunning ())
483 it->second.first.m_inactivityEvent.Cancel ();
491 uint16_t currentStartingSeq = it->second.first.GetStartingSequence ();
496 for (
PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd; )
498 currentSeq = (*queueIt)->GetHeader ().GetSequenceNumber ();
500 (*queueIt)->GetHeader ().GetFragmentNumber ()))
508 foundFirstLost =
true;
515 queueIt = it->second.second.erase (queueIt);
525 for (
PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd; )
527 currentSeq = (*queueIt)->GetHeader ().GetSequenceNumber ();
530 it->second.first.NotifyAckedMpdu (*queueIt);
547 queueIt = it->second.second.erase (queueIt);
567 for (
auto& item : it->second.second)
574 it->second.second.clear ();
585 while (!it->second.second.empty ())
591 it->second.second.pop_front ();
613 if (!mpdu->GetHeader ().IsQosData ())
619 Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
620 uint8_t tid = mpdu->GetHeader ().GetQosTid ();
628 uint16_t currStartingSeq = it->second.first.GetStartingSequence ();
639 it->second.first.NotifyDiscardedMpdu (mpdu);
642 NS_LOG_DEBUG (
"Schedule a Block Ack Request for agreement (" << recipient <<
", " << +tid <<
")");
649 hdr.
SetAddr2 (mpdu->GetHeader ().GetAddr2 ());
650 hdr.
SetAddr3 (mpdu->GetHeader ().GetAddr3 ());
656 ScheduleBar (Create<const WifiMacQueueItem> (bar, hdr));
668 reqHdr.SetTidInfo (tid);
669 reqHdr.SetStartingSequence ((*it).second.first.GetStartingSequence ());
677 NS_ASSERT (bar->GetHeader ().IsBlockAckReq ());
680 bar->GetPacket ()->PeekHeader (reqHdr);
681 uint8_t tid = reqHdr.GetTidInfo ();
682 Bar request (bar, tid, skipIfNoDataQueued);
685 for (std::list<Bar>::const_iterator i =
m_bars.begin (); i !=
m_bars.end (); i++)
687 if (i->bar->GetHeader ().GetAddr1 () == bar->GetHeader ().GetAddr1 () && i->tid == tid)
690 m_bars.insert (i, request);
695 if (bar->GetHeader ().IsRetry ())
697 m_bars.push_front (request);
701 m_bars.push_back (request);
718 if (!it->second.first.IsEstablished ())
723 it->second.first.SetStartingSequence (startingSeq);
732 if (!it->second.first.IsRejected ())
745 if (!it->second.first.IsNoReply ())
759 if (!it->second.first.IsReset ())
780 uint32_t packets =
m_queue->GetNPacketsByTidAndAddress (tid, recipient) +
799 for (
auto& mpdu : it->second.second)
832 uint16_t itSeq = (*it)->GetHeader ().GetSequenceNumber ();
834 if (agreementIt->second.first.GetDistance (itSeq) >= agreementIt->second.first.GetDistance (startSeq)
835 && agreementIt->second.first.GetDistance (itSeq) <= agreementIt->second.first.GetDistance (endSeq))
837 NS_LOG_DEBUG (
"Removing frame with seqnum = " << itSeq);
855 uint16_t currStartingSeq = agreementIt->second.first.GetStartingSequence ();
858 "The new starting sequence number is an old sequence number");
860 if (startingSeq == currStartingSeq)
871 while (it != agreementIt->second.second.end ())
873 uint16_t itSeq = (*it)->GetHeader ().GetSequenceNumber ();
875 if (agreementIt->second.first.GetDistance (itSeq) <= agreementIt->second.first.GetDistance (lastRemovedSeq))
877 NS_LOG_DEBUG (
"Removing frame with seqnum = " << itSeq);
878 it = agreementIt->second.second.erase (it);
931 NS_ASSERT (mpdu->GetHeader ().IsQosData ());
933 uint8_t tid = mpdu->GetHeader ().GetQosTid ();
934 Mac48Address recipient = mpdu->GetHeader ().GetAddr1 ();
939 uint16_t mpduDist = agreementIt->second.first.GetDistance (mpdu->GetHeader ().GetSequenceNumber ());
947 WifiMacQueue::ConstIterator it =
m_retryPackets->PeekByTidAndAddress (tid, recipient);
951 if (mpdu->GetHeader ().GetSequenceControl () == (*it)->GetHeader ().GetSequenceControl ())
953 NS_LOG_DEBUG (
"Packet already in the retransmit queue");
957 uint16_t dist = agreementIt->second.first.GetDistance ((*it)->GetHeader ().GetSequenceNumber ());
959 if (mpduDist < dist ||
960 (mpduDist == dist && mpdu->GetHeader ().GetFragmentNumber () < (*it)->GetHeader ().GetFragmentNumber ()))
967 mpdu->GetHeader ().SetRetry ();
978 size = it->second.first.GetBufferSize ();
990 seqNum = it->second.first.GetStartingSequence ();
void SetUnblockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
Set unblock destination callback.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Simulation virtual time values and global simulation resolution.
Smart pointer class similar to boost::intrusive_ptr.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void NotifyMissedBlockAck(Mac48Address recipient, uint8_t tid)
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
Maintains the state and information about transmitted MPDUs with Ack Policy set to Block Ack for an o...
void RemoveOldPackets(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
Remove packets from the retransmit queue and from the queue of outstanding packets that become old af...
std::list< Ptr< WifiMacQueueItem > >::iterator PacketQueueI
typedef for an iterator for PacketQueue.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
std::map< std::pair< Mac48Address, uint8_t >, std::pair< OriginatorBlockAckAgreement, PacketQueue > >::const_iterator AgreementsCI
typedef for a const iterator for Agreements.
void CreateAgreement(const MgtAddBaRequestHeader *reqHdr, Mac48Address recipient)
uint32_t GetNBufferedPackets(Mac48Address recipient, uint8_t tid) const
void ScheduleBar(Ptr< const WifiMacQueueItem > bar, bool skipIfNoDataQueued=false)
TracedCallback< Time, Mac48Address, uint8_t, OriginatorBlockAckAgreement::State > m_agreementState
The trace source fired when a state transition occurred.
uint8_t m_blockAckThreshold
block ack threshold
Agreements m_agreements
This data structure contains, for each block ack agreement (recipient, TID), a set of packets for whi...
void NotifyMissedAck(Ptr< WifiMacQueueItem > mpdu)
Invoked upon missed reception of an Ack frame after the transmission of a QoS data frame sent under a...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
const uint16_t SEQNO_SPACE_HALF_SIZE
Size of the half the space of sequence numbers (used to determine old packets)
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
std::map< std::pair< Mac48Address, uint8_t >, std::pair< OriginatorBlockAckAgreement, PacketQueue > >::iterator AgreementsI
typedef for an iterator for Agreements.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
bool QosUtilsIsOldPacket(uint16_t startingSeq, uint16_t seqNumber)
This function checks if packet with sequence number seqNumber is an "old" packet. ...
CtrlBAckRequestHeader GetBlockAckReqHeader(Mac48Address recipient, uint8_t tid) const
BlockAckRequest frame information.
TxOk m_txOkCallback
transmit OK callback
bool ExistsAgreementInState(Mac48Address recipient, uint8_t tid, OriginatorBlockAckAgreement::State state) const
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
void RemoveFromRetryQueue(Mac48Address address, uint8_t tid, uint16_t seq)
Remove an item from retransmission queue.
void SetTxFailedCallback(TxFailed callback)
void NotifyDiscardedMpdu(Ptr< const WifiMacQueueItem > mpdu)
Ptr< WifiMacQueue > GetRetransmitQueue(void)
void NotifyAgreementEstablished(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
void UpdateAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address recipient)
uint16_t GetTimeout(void) const
Return the timeout.
void SetQueue(const Ptr< WifiMacQueue > queue)
void SetBlockAckType(BlockAckType bAckType)
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > manager)
Set up WifiRemoteStationManager associated with this BlockAckManager.
static TypeId GetTypeId(void)
Get the type ID.
bool GetHtSupported(void) const
Return whether the device has HT capability support enabled.
void NotifyAgreementRejected(Mac48Address recipient, uint8_t tid)
bool ExistsAgreement(Mac48Address recipient, uint8_t tid) const
std::list< Ptr< WifiMacQueueItem > >::const_iterator PacketQueueCI
typedef for a const iterator for PacketQueue.
Ptr< MacTxMiddle > m_txMiddle
the MacTxMiddle
void SetBlockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
Set block destination callback.
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...
void DestroyAgreement(Mac48Address recipient, uint8_t tid)
static const ConstIterator EMPTY
Invalid iterator to signal an empty queue.
void SetState(State state)
Set the current state.
void SetTxOkCallback(TxOk callback)
Ptr< const WifiMacQueueItem > GetBar(bool remove=true)
Returns the next BlockAckRequest to send, if any.
bool HasPackets(void)
Returns true if there are packets that need of retransmission or at least a BAR is scheduled...
uint16_t GetRecipientBufferSize(Mac48Address recipient, uint8_t tid) const
This function returns the buffer size negotiated with the recipient.
void InsertInRetryQueue(Ptr< WifiMacQueueItem > mpdu)
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void InactivityTimeout(Mac48Address recipient, uint8_t tid)
Inactivity timeout function.
Callback< void, Mac48Address, uint8_t, bool > m_blockAckInactivityTimeout
BlockAck inactivity timeout callback.
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...
void DiscardOutstandingMpdus(Mac48Address recipient, uint8_t tid)
Callback< void, Mac48Address, uint8_t > m_blockPackets
block packets callback
void StorePacket(Ptr< WifiMacQueueItem > mpdu)
std::list< Ptr< WifiMacQueueItem > > PacketQueue
typedef for a list of WifiMacQueueItem.
Ptr< WifiMacQueue > m_retryPackets
This list contains all iterators to stored packets that need to be retransmitted. ...
static Time Now(void)
Return the current simulation virtual time.
State
Represents the state for this agreement.
void NotifyAgreementReset(Mac48Address recipient, uint8_t tid)
void SetBlockAckInactivityCallback(Callback< void, Mac48Address, uint8_t, bool > callback)
Set BlockAck inactivity callback.
uint16_t GetOriginatorStartingSequence(Mac48Address recipient, uint8_t tid) const
This function returns the starting sequence number of the transmit window.
void NotifyGotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, double dataSnr, WifiTxVector dataTxVector)
void SetDelayedBlockAck(void)
Set block ack policy to delayed Ack.
EventId m_inactivityEvent
inactivity event
void SetAmsduSupport(bool supported)
Enable or disable A-MSDU support.
bool SwitchToBlockAckIfNeeded(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
Callback< void, Mac48Address, uint8_t > m_unblockPackets
unblock packets callback
std::list< Bar > m_bars
list of BARs
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Ptr< const WifiMacQueueItem > bar
BlockAckRequest.
void SetTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set the MacTxMiddle.
void SetBlockAckThreshold(uint8_t nPackets)
BlockAckType m_blockAckType
BlockAck type.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
void NotifyAgreementNoReply(Mac48Address recipient, uint8_t tid)
const uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
void SetImmediateBlockAck(void)
Set block ack policy to immediate Ack.
void SetTimeout(uint16_t timeout)
Set timeout.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
A base class which provides memory management and object aggregation.
Manages all block ack agreements for an originator station.
bool IsNull(void) const
Check for null implementation.
TxFailed m_txFailedCallback
transmit failed callback
Ptr< WifiRemoteStationManager > m_stationManager
the station manager
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
bool skipIfNoDataQueued
do not send if there is no data queued
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
void InitTxWindow(void)
Initialize the originator's transmit window by setting its size and starting sequence number equal to...
void AddHeader(const Header &header)
Add header to this packet.
Ptr< WifiMacQueue > m_queue
queue
void ReportAmpduTxStatus(Mac48Address address, uint8_t nSuccessfulMpdus, uint8_t nFailedMpdus, double rxSnr, double dataSnr, WifiTxVector dataTxVector)
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
BlockAckType
The different block ack policies.