22 #include "ns3/assert.h"
23 #include "ns3/simulator.h"
24 #include "ns3/fatal-error.h"
59 recipient (recipient),
63 NS_LOG_FUNCTION (
this << bar << recipient << static_cast<uint32_t> (tid) << immediate);
90 NS_LOG_FUNCTION (
this << recipient << static_cast<uint32_t> (tid) << state);
92 it =
m_agreements.find (std::make_pair (recipient, tid));
98 return it->second.first.IsInactive ();
100 return it->second.first.IsEstablished ();
102 return it->second.first.IsPending ();
104 return it->second.first.IsUnsuccessful ();
116 std::pair<Mac48Address, uint8_t> key (recipient, reqHdr->
GetTid ());
121 agreement.SetBufferSize (64);
122 agreement.SetWinEnd ((agreement.GetStartingSequence () + agreement.GetBufferSize () - 1) % 4096);
128 agreement.SetImmediateBlockAck ();
132 agreement.SetDelayedBlockAck ();
136 std::pair<OriginatorBlockAckAgreement, PacketQueue> value (agreement, queue);
150 if ((*i)->hdr.GetAddr1 () == recipient && (*i)->hdr.GetQosTid () == tid)
161 for (std::list<Bar>::iterator i =
m_bars.begin (); i !=
m_bars.end (); )
163 if (i->recipient == recipient && i->tid == tid)
179 uint8_t tid = respHdr->
GetTid ();
217 Item item (packet, hdr, tStamp);
221 for (; queueIt != it->second.second.end (); )
223 if (((hdr.
GetSequenceNumber () - queueIt->hdr.GetSequenceNumber () + 4096) % 4096) > 2047)
225 queueIt = it->second.second.insert (queueIt, item);
233 if (queueIt == it->second.second.end ())
235 it->second.second.push_back (item);
262 if ((*it)->hdr.IsQosData ())
264 tid = (*it)->hdr.GetQosTid ();
268 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
270 recipient = (*it)->hdr.GetAddr1 ();
273 if (
QosUtilsIsOldPacket (agreement->second.first.GetStartingSequence (),(*it)->hdr.GetSequenceNumber ()))
276 NS_LOG_DEBUG (
"The Retry packet have sequence number < WinStartO --> Discard " << (*it)->hdr.GetSequenceNumber () <<
" " << agreement->second.first.GetStartingSequence ());
277 agreement->second.second.erase ((*it));
281 else if ((*it)->hdr.GetSequenceNumber () > (agreement->second.first.GetStartingSequence () + 63) % 4096)
283 agreement->second.first.SetStartingSequence ((*it)->hdr.GetSequenceNumber ());
285 packet = (*it)->packet->
Copy ();
295 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
298 if (!agreement->second.first.IsHtSupported ()
315 i->second.second.erase (*it);
339 if ((*it)->hdr.IsQosData ())
341 tid = (*it)->hdr.GetQosTid ();
345 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
347 recipient = (*it)->hdr.GetAddr1 ();
350 packet = (*it)->packet->
Copy ();
359 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
362 if (!agreement->second.first.IsHtSupported ()
396 if (!(*it)->hdr.IsQosData ())
398 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
400 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
402 if (
QosUtilsIsOldPacket (agreement->second.first.GetStartingSequence (),(*it)->hdr.GetSequenceNumber ()))
405 NS_LOG_DEBUG (
"The Retry packet have sequence number < WinStartO --> Discard " << (*it)->hdr.GetSequenceNumber () <<
" " << agreement->second.first.GetStartingSequence ());
406 agreement->second.second.erase ((*it));
411 else if ((*it)->hdr.GetSequenceNumber () > (agreement->second.first.GetStartingSequence () + 63) % 4096)
413 agreement->second.first.SetStartingSequence ((*it)->hdr.GetSequenceNumber ());
415 packet = (*it)->packet->
Copy ();
418 *tstamp = (*it)->timestamp;
421 if (!agreement->second.first.IsHtSupported ()
452 if (!(*it)->hdr.IsQosData ())
454 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
456 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid && (*it)->hdr.GetSequenceNumber () == seqnumber)
463 i->second.second.erase ((*it));
497 uint32_t nPackets = 0;
502 uint16_t currentSeq = 0;
503 while (queueIt != (*it).second.second.end ())
505 currentSeq = (*queueIt).hdr.GetSequenceNumber ();
508 while (queueIt != (*it).second.second.end () && (*queueIt).hdr.GetSequenceNumber () == currentSeq)
522 uint32_t nPackets = 0;
523 uint16_t currentSeq = 0;
526 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
529 if (!(*it)->hdr.IsQosData ())
531 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
533 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
535 currentSeq = (*it)->hdr.GetSequenceNumber ();
538 while (it !=
m_retryPackets.end () && (*it)->hdr.GetSequenceNumber () == currentSeq)
570 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
574 if (!(*it)->hdr.IsQosData ())
576 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
578 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid && currentSeq == (*it)->hdr.GetSequenceNumber ())
591 uint16_t sequenceFirstLost = 0;
597 bool foundFirstLost =
false;
598 uint32_t nSuccessfulMpdus = 0;
599 uint32_t nFailedMpdus = 0;
603 if (it->second.first.m_inactivityEvent.IsRunning ())
608 it->second.first.m_inactivityEvent.Cancel ();
617 for (
PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd; )
620 (*queueIt).hdr.GetFragmentNumber ()))
623 queueIt = it->second.second.erase (queueIt);
629 foundFirstLost =
true;
630 sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber ();
631 (*it).second.first.SetStartingSequence (sequenceFirstLost);
634 if (!
AlreadyExists ((*queueIt).hdr.GetSequenceNumber (),recipient,tid))
644 for (
PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd; )
648 uint16_t currentSeq = (*queueIt).hdr.GetSequenceNumber ();
649 while (queueIt != queueEnd
650 && (*queueIt).hdr.GetSequenceNumber () == currentSeq)
657 queueIt = it->second.second.erase (queueIt);
664 foundFirstLost =
true;
665 sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber ();
666 (*it).second.first.SetStartingSequence (sequenceFirstLost);
673 if (!
AlreadyExists ((*queueIt).hdr.GetSequenceNumber (),recipient,tid))
686 it->second.first.CompleteExchange ();
716 if ((*it).second.first.IsBlockAckRequestNeeded ()
755 NS_LOG_FUNCTION (
this << recipient << static_cast<uint32_t> (tid) << startingSeq);
760 it->second.first.SetStartingSequence (startingSeq);
778 NS_LOG_FUNCTION (
this << recipient << static_cast<uint32_t> (tid) << nextSeqNumber);
790 nextSeq = nextSeqNumber;
792 it->second.first.NotifyMpduTransmission (nextSeq);
798 Bar request (bar, recipient, tid, it->second.first.IsImmediateBlockAck ());
799 m_bars.push_back (request);
814 NS_LOG_FUNCTION (
this << recipient << static_cast<uint32_t> (tid) << startingSeq);
871 if ((seqNumber + 63) < it->second.first.GetStartingSequence ())
887 if (j->second.second.empty ())
893 for (
PacketQueueI i = j->second.second.begin (); i != j->second.second.end (); i++)
905 if ((*it)->hdr.GetAddr1 () == j->second.first.GetPeer ()
906 && (*it)->hdr.GetQosTid () == j->second.first.GetTid ()
907 && (*it)->hdr.GetSequenceNumber () == i->hdr.GetSequenceNumber ())
918 j->second.second.erase (j->second.second.begin (), end);
919 j->second.first.SetStartingSequence (end->hdr.GetSequenceNumber ());
962 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
965 if (!(*it)->hdr.IsQosData ())
967 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
969 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
971 return (*it)->hdr.GetSequenceNumber ();
993 NS_LOG_INFO (
"Adding to retry queue " << (*item).hdr.GetSequenceNumber ());
1002 if (((item->hdr.GetSequenceNumber () - (*it)->hdr.GetSequenceNumber () + 4096) % 4096) > 2047)
void SetUnblockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
uint8_t GetTid(void) const
Return the Traffic ID (TID).
Simulation virtual time values and global simulation resolution.
void NotifyGotBlockAck(const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, WifiMode txMode, double dataSnr)
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
std::list< Item > PacketQueue
typedef for a list of Item struct.
Maintains the state and information about transmitted MPDUs with ack policy block ack for an originat...
uint16_t GetTimeout(void) const
Return the timeout.
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)
Ptr< const Packet > PeekNextPacketByTidAndAddress(WifiMacHeader &hdr, Mac48Address recipient, uint8_t tid, Time *timestamp)
void StorePacket(Ptr< const Packet > packet, const WifiMacHeader &hdr, Time tStamp)
uint8_t m_blockAckThreshold
Agreements m_agreements
This data structure contains, for each block ack agreement (recipient, tid), a set of packets for whi...
bool IsNull(void) const
Check for null implementation.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
bool HasBar(struct Bar &bar)
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
void InactivityTimeout(Mac48Address, uint8_t)
std::map< std::pair< Mac48Address, uint8_t >, std::pair< OriginatorBlockAckAgreement, PacketQueue > >::iterator AgreementsI
typedef for an iterator for Agreements.
void SetBlockAckType(enum BlockAckType bAckType)
void ReportAmpduTxStatus(Mac48Address address, uint8_t tid, uint32_t nSuccessfulMpdus, uint32_t nFailedMpdus, double rxSnr, double dataSnr)
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
#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. ...
bool HasPackets(void) const
Returns true if there are packets that need of retransmission or at least a BAR is scheduled...
BlockAckType
Enumeration for different block ACK policies.
Ptr< const Packet > PeekNextPacket(WifiMacHeader &hdr)
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
uint16_t GetStartingSequence(void) const
Return the starting squence number.
Handles sequence numbering of IEEE 802.11 data frames.
void SetTxFailedCallback(TxFailed callback)
Ptr< Packet > ScheduleBlockAckReqIfNeeded(Mac48Address recipient, uint8_t tid)
void SetQueue(Ptr< WifiMacQueue > queue)
void NotifyAgreementEstablished(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
void UpdateAgreement(const MgtAddBaResponseHeader *respHdr, Mac48Address recipient)
uint32_t GetNRetryNeededPackets(Mac48Address recipient, uint8_t tid) const
uint32_t GetNextPacketSize(void) const
uint16_t GetSeqNumOfNextRetryPacket(Mac48Address recipient, uint8_t tid) const
void NotifyAgreementUnsuccessful(Mac48Address recipient, uint8_t tid)
void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > manager)
Set up WifiRemoteStationManager associated with this BlockAckManager.
void InsertInRetryQueue(PacketQueueI item)
bool HasOtherFragments(uint16_t sequenceNumber) const
std::string GetUniqueName(void) const
std::list< PacketQueueI > m_retryPackets
This list contains all iterators to stored packets that need to be retransmitted. ...
void SetTxMiddle(MacTxMiddle *txMiddle)
void SetBlockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
void DestroyAgreement(Mac48Address recipient, uint8_t tid)
void SetTxOkCallback(TxOk callback)
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool RemovePacket(uint8_t tid, Mac48Address recipient, uint16_t seqnumber)
Remove a packet after you peek in the queue and get it.
Callback< void, Mac48Address, uint8_t, bool > m_blockAckInactivityTimeout
QosAckPolicy
ACK policy for QoS frames.
bool ExistsAgreementInState(Mac48Address recipient, uint8_t tid, enum OriginatorBlockAckAgreement::State state) const
Callback< void, Mac48Address, uint8_t > m_blockPackets
bool AlreadyExists(uint16_t currentSeq, Mac48Address recipient, uint8_t tid)
Checks if the packet already exists in the retransmit queue or not if it does then it doesn't add it ...
Ptr< const Packet > GetNextPacket(WifiMacHeader &hdr)
static Time Now(void)
Return the current simulation virtual time.
void SetBlockAckInactivityCallback(Callback< void, Mac48Address, uint8_t, bool > callback)
void SetMaxPacketDelay(Time maxDelay)
void NotifyMpduTransmission(Mac48Address recipient, uint8_t tid, uint16_t nextSeqNumber, WifiMacHeader::QosAckPolicy policy)
bool HasHtSupported(void) const
Return whether the device has HT capability support enabled.
void SetDelayedBlockAck(void)
Set Block ACK policy to delayed ACK.
EventId m_inactivityEvent
bool NeedBarRetransmission(uint8_t tid, uint16_t seqNumber, Mac48Address recipient)
This function returns true if the lifetime of the packets a BAR refers to didn't expire yet else it r...
void SetAmsduSupport(bool supported)
Enable or disable A-MSDU support.
A struct for packet, Wifi header, and timestamp.
bool SwitchToBlockAckIfNeeded(Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
std::list< Item >::const_iterator PacketQueueCI
typedef for a const iterator for PacketQueue.
Callback< void, Mac48Address, uint8_t > m_unblockPackets
uint32_t GetNBufferedPackets(Mac48Address recipient, uint8_t tid) const
enum BlockAckType m_blockAckType
void CleanupBuffers(void)
This method removes packets whose lifetime was exceeded.
void SetBlockAckThreshold(uint8_t nPackets)
void CompleteAmpduExchange(Mac48Address recipient, uint8_t tid)
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
State
Represents the state for this agreement.
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.
void SetState(enum State state)
bool ExistsAgreement(Mac48Address recipient, uint8_t tid) const
TxFailed m_txFailedCallback
Ptr< WifiRemoteStationManager > m_stationManager
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
uint16_t GetNextSeqNumberByTidAndAddress(uint8_t tid, Mac48Address addr) const
Return the next sequence number for the Traffic ID and destination.
Ptr< const Packet > packet
void AddHeader(const Header &header)
Add header to this packet.
void TearDownBlockAck(Mac48Address recipient, uint8_t tid)
Ptr< WifiMacQueue > m_queue
void CompleteExchange(void)
std::list< Item >::iterator PacketQueueI
typedef for an iterator for PacketQueue.