22 #include "ns3/simulator.h"
52 recipient (recipient),
56 NS_LOG_FUNCTION (
this << bar << recipient << (uint16_t)tid << immediate);
66 .SetGroupName (
"Wifi")
98 it =
m_agreements.find (std::make_pair (recipient, tid));
104 return it->second.first.IsInactive ();
106 return it->second.first.IsEstablished ();
108 return it->second.first.IsPending ();
110 return it->second.first.IsUnsuccessful ();
122 std::pair<Mac48Address, uint8_t> key (recipient, reqHdr->
GetTid ());
127 agreement.SetBufferSize (64);
128 agreement.SetWinEnd ((agreement.GetStartingSequence () + agreement.GetBufferSize () - 1) % 4096);
134 agreement.SetImmediateBlockAck ();
138 agreement.SetDelayedBlockAck ();
142 std::pair<OriginatorBlockAckAgreement, PacketQueue> value (agreement, queue);
156 if ((*i)->hdr.GetAddr1 () == recipient && (*i)->hdr.GetQosTid () == tid)
167 for (std::list<Bar>::const_iterator i =
m_bars.begin (); i !=
m_bars.end (); )
169 if (i->recipient == recipient && i->tid == tid)
185 uint8_t tid = respHdr->
GetTid ();
223 Item item (packet, hdr, tStamp);
227 for (; queueIt != it->second.second.end (); )
229 if (((hdr.
GetSequenceNumber () - queueIt->hdr.GetSequenceNumber () + 4096) % 4096) > 2047)
231 queueIt = it->second.second.insert (queueIt, item);
239 if (queueIt == it->second.second.end ())
241 it->second.second.push_back (item);
265 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
268 if ((*it)->hdr.IsQosData ())
270 tid = (*it)->hdr.GetQosTid ();
274 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
276 recipient = (*it)->hdr.GetAddr1 ();
279 if (
QosUtilsIsOldPacket (agreement->second.first.GetStartingSequence (),(*it)->hdr.GetSequenceNumber ()))
282 NS_LOG_DEBUG (
"The Retry packet have sequence number < WinStartO --> Discard " << (*it)->hdr.GetSequenceNumber () <<
" " << agreement->second.first.GetStartingSequence ());
283 agreement->second.second.erase ((*it));
287 else if ((*it)->hdr.GetSequenceNumber () > (agreement->second.first.GetStartingSequence () + 63) % 4096)
289 agreement->second.first.SetStartingSequence ((*it)->hdr.GetSequenceNumber ());
291 packet = (*it)->packet->
Copy ();
301 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
304 if (!agreement->second.first.IsHtSupported ()
321 i->second.second.erase (*it);
342 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
345 if ((*it)->hdr.IsQosData ())
347 tid = (*it)->hdr.GetQosTid ();
351 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
353 recipient = (*it)->hdr.GetAddr1 ();
356 packet = (*it)->packet->
Copy ();
365 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
368 if (!agreement->second.first.IsHtSupported ()
399 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
402 if (!(*it)->hdr.IsQosData ())
404 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
406 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
408 if (
QosUtilsIsOldPacket (agreement->second.first.GetStartingSequence (),(*it)->hdr.GetSequenceNumber ()))
411 NS_LOG_DEBUG (
"The Retry packet have sequence number < WinStartO --> Discard " << (*it)->hdr.GetSequenceNumber () <<
" " << agreement->second.first.GetStartingSequence ());
412 agreement->second.second.erase ((*it));
417 else if ((*it)->hdr.GetSequenceNumber () > (agreement->second.first.GetStartingSequence () + 63) % 4096)
419 agreement->second.first.SetStartingSequence ((*it)->hdr.GetSequenceNumber ());
421 packet = (*it)->packet->
Copy ();
424 *tstamp = (*it)->timestamp;
427 if (!agreement->second.first.IsHtSupported ()
455 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
458 if (!(*it)->hdr.IsQosData ())
460 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
462 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid && (*it)->hdr.GetSequenceNumber () == seqnumber)
469 i->second.second.erase ((*it));
503 uint32_t nPackets = 0;
508 uint16_t currentSeq = 0;
509 while (queueIt != (*it).second.second.end ())
511 currentSeq = (*queueIt).hdr.GetSequenceNumber ();
514 while (queueIt != (*it).second.second.end () && (*queueIt).hdr.GetSequenceNumber () == currentSeq)
528 uint32_t nPackets = 0;
529 uint16_t currentSeq = 0;
532 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
535 if (!(*it)->hdr.IsQosData ())
537 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
539 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
541 currentSeq = (*it)->hdr.GetSequenceNumber ();
544 while (it !=
m_retryPackets.end () && (*it)->hdr.GetSequenceNumber () == currentSeq)
576 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
580 if (!(*it)->hdr.IsQosData ())
582 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
584 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid && currentSeq == (*it)->hdr.GetSequenceNumber ())
597 uint16_t sequenceFirstLost = 0;
603 bool foundFirstLost =
false;
604 uint32_t nSuccessfulMpdus = 0;
605 uint32_t nFailedMpdus = 0;
609 if (it->second.first.m_inactivityEvent.IsRunning ())
614 it->second.first.m_inactivityEvent.Cancel ();
623 for (
PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd; )
626 (*queueIt).hdr.GetFragmentNumber ()))
630 queueIt = it->second.second.erase (queueIt);
636 foundFirstLost =
true;
637 sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber ();
638 (*it).second.first.SetStartingSequence (sequenceFirstLost);
641 if (!
AlreadyExists ((*queueIt).hdr.GetSequenceNumber (),recipient,tid))
651 for (
PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd; )
653 uint16_t currentSeq = (*queueIt).hdr.GetSequenceNumber ();
656 while (queueIt != queueEnd
657 && (*queueIt).hdr.GetSequenceNumber () == currentSeq)
665 queueIt = it->second.second.erase (queueIt);
672 foundFirstLost =
true;
673 sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber ();
674 (*it).second.first.SetStartingSequence (sequenceFirstLost);
681 if (!
AlreadyExists ((*queueIt).hdr.GetSequenceNumber (),recipient,tid))
694 it->second.first.CompleteExchange ();
724 if ((*it).second.first.IsBlockAckRequestNeeded ()
763 NS_LOG_FUNCTION (
this << recipient << static_cast<uint32_t> (tid) << startingSeq);
768 it->second.first.SetStartingSequence (startingSeq);
786 NS_LOG_FUNCTION (
this << recipient << static_cast<uint32_t> (tid) << nextSeqNumber);
798 nextSeq = nextSeqNumber;
800 it->second.first.NotifyMpduTransmission (nextSeq);
806 Bar request (bar, recipient, tid, it->second.first.IsImmediateBlockAck ());
807 m_bars.push_back (request);
879 if ((seqNumber + 63) < it->second.first.GetStartingSequence ())
893 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
896 if ((*it)->hdr.GetAddr1 () == address
897 && (*it)->hdr.GetQosTid () == tid
898 && (*it)->hdr.GetSequenceNumber () == seq)
915 if (j->second.second.empty ())
921 for (
PacketQueueI i = j->second.second.begin (); i != j->second.second.end (); i++)
931 j->second.first.GetTid (),
932 i->hdr.GetSequenceNumber ());
935 j->second.second.erase (j->second.second.begin (), end);
936 j->second.first.SetStartingSequence (end->hdr.GetSequenceNumber ());
979 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
982 if (!(*it)->hdr.IsQosData ())
984 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
986 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
988 return (*it)->hdr.GetSequenceNumber ();
1010 NS_LOG_INFO (
"Adding to retry queue " << (*item).hdr.GetSequenceNumber ());
1019 if (((item->hdr.GetSequenceNumber () - (*it)->hdr.GetSequenceNumber () + 4096) % 4096) > 2047)
void SetUnblockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
Set unblock destination 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.
#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)
Ptr< const Packet > PeekNextPacketByTidAndAddress(WifiMacHeader &hdr, Mac48Address recipient, uint8_t tid, Time *timestamp)
Peek in retransmit queue and get the next packet having address indicated by type equals to addr...
void StorePacket(Ptr< const Packet > packet, const WifiMacHeader &hdr, Time tStamp)
uint8_t m_blockAckThreshold
bock ack threshold
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.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
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. ...
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...
TxOk m_txOkCallback
transmit ok callback
uint16_t GetStartingSequence(void) const
Return the starting squence number.
void RemoveFromRetryQueue(Mac48Address address, uint8_t tid, uint16_t seq)
Remove items from retransmission queue.
void SetTxFailedCallback(TxFailed callback)
Ptr< Packet > ScheduleBlockAckReqIfNeeded(Mac48Address recipient, uint8_t tid)
bool AlreadyExists(uint16_t currentSeq, Mac48Address recipient, uint8_t tid) const
Checks if the packet already exists in the retransmit queue or not if it does then it doesn't add it ...
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)
void SetQueue(const Ptr< WifiMacQueue > queue)
uint32_t GetNRetryNeededPackets(Mac48Address recipient, uint8_t tid) const
uint32_t GetNextPacketSize(void) const
void SetBlockAckType(BlockAckType bAckType)
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > manager)
Set up WifiRemoteStationManager associated with this BlockAckManager.
uint16_t GetSeqNumOfNextRetryPacket(Mac48Address recipient, uint8_t tid) const
void NotifyAgreementUnsuccessful(Mac48Address recipient, uint8_t tid)
static TypeId GetTypeId(void)
Get the type ID.
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. ...
Ptr< MacTxMiddle > m_txMiddle
the MacTxMiddle
void SetBlockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
Set block destination callback.
void DestroyAgreement(Mac48Address recipient, uint8_t tid)
void SetState(State state)
Set the current state.
void SetTxOkCallback(TxOk callback)
bool HasBar(Bar &bar)
Returns true if the BAR is scheduled.
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.
void InactivityTimeout(Mac48Address recipient, uint8_t tid)
Inactivity timeout function.
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
block ack inactivity timeout callback
QosAckPolicy
ACK policy for QoS frames.
Callback< void, Mac48Address, uint8_t > m_blockPackets
block packets callback
Ptr< const Packet > GetNextPacket(WifiMacHeader &hdr)
bool ExistsAgreementInState(Mac48Address recipient, uint8_t tid, OriginatorBlockAckAgreement::State state) const
static Time Now(void)
Return the current simulation virtual time.
void SetBlockAckInactivityCallback(Callback< void, Mac48Address, uint8_t, bool > callback)
Set block ack inactivity 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
inactivity event
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
unblock packets callback
uint32_t GetNBufferedPackets(Mac48Address recipient, uint8_t tid) const
std::list< Bar > m_bars
list of BARs
void CleanupBuffers(void)
This method removes packets whose lifetime was exceeded.
void SetTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set the MacTxMiddle.
void SetBlockAckThreshold(uint8_t nPackets)
void CompleteAmpduExchange(Mac48Address recipient, uint8_t tid)
BlockAckType m_blockAckType
bock ack type
#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.
Time m_maxDelay
maximum delay
void SetTimeout(uint16_t timeout)
Set timeout.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
void ReportAmpduTxStatus(Mac48Address address, uint8_t tid, uint8_t nSuccessfulMpdus, uint8_t nFailedMpdus, double rxSnr, double dataSnr)
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
A base class which provides memory management and object aggregation.
Manages all block ack agreements for an originator station.
bool ExistsAgreement(Mac48Address recipient, uint8_t tid) const
TxFailed m_txFailedCallback
transmit failed callback
Ptr< WifiRemoteStationManager > m_stationManager
the station manager
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.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Ptr< const Packet > packet
packet
void AddHeader(const Header &header)
Add header to this packet.
void TearDownBlockAck(Mac48Address recipient, uint8_t tid)
Ptr< WifiMacQueue > m_queue
queue
void CompleteExchange(void)
Complete exchange function.
std::list< Item >::iterator PacketQueueI
typedef for an iterator for PacketQueue.