22 #include "ns3/simulator.h" 50 recipient (recipient),
64 .SetGroupName (
"Wifi")
96 it =
m_agreements.find (std::make_pair (recipient, tid));
102 return it->second.first.IsInactive ();
104 return it->second.first.IsEstablished ();
106 return it->second.first.IsPending ();
108 return it->second.first.IsUnsuccessful ();
120 std::pair<Mac48Address, uint8_t> key (recipient, reqHdr->
GetTid ());
125 agreement.SetBufferSize (64);
126 agreement.SetWinEnd ((agreement.GetStartingSequence () + agreement.GetBufferSize () - 1) % 4096);
132 agreement.SetImmediateBlockAck ();
136 agreement.SetDelayedBlockAck ();
140 std::pair<OriginatorBlockAckAgreement, PacketQueue> value (agreement, queue);
154 if ((*i)->hdr.GetAddr1 () == recipient && (*i)->hdr.GetQosTid () == tid)
165 for (std::list<Bar>::const_iterator i =
m_bars.begin (); i !=
m_bars.end (); )
167 if (i->recipient == recipient && i->tid == tid)
183 uint8_t tid = respHdr->
GetTid ();
221 Item item (packet, hdr, tStamp);
225 for (; queueIt != it->second.second.end (); )
227 if (((hdr.
GetSequenceNumber () - queueIt->hdr.GetSequenceNumber () + 4096) % 4096) > 2047)
229 queueIt = it->second.second.insert (queueIt, item);
237 if (queueIt == it->second.second.end ())
239 it->second.second.push_back (item);
263 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
266 if ((*it)->hdr.IsQosData ())
268 tid = (*it)->hdr.GetQosTid ();
272 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
274 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 ());
292 packet = (*it)->packet->
Copy ();
301 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
304 if (!agreement->second.first.IsHtSupported ()
323 i->second.second.erase (*it);
347 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
350 if (!(*it)->hdr.IsQosData ())
352 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
354 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
356 if (
QosUtilsIsOldPacket (agreement->second.first.GetStartingSequence (),(*it)->hdr.GetSequenceNumber ()))
359 NS_LOG_DEBUG (
"The Retry packet have sequence number < WinStartO --> Discard " << (*it)->hdr.GetSequenceNumber () <<
" " << agreement->second.first.GetStartingSequence ());
360 agreement->second.second.erase ((*it));
365 else if ((*it)->hdr.GetSequenceNumber () > (agreement->second.first.GetStartingSequence () + 63) % 4096)
367 agreement->second.first.SetStartingSequence ((*it)->hdr.GetSequenceNumber ());
369 packet = (*it)->packet->
Copy ();
372 *tstamp = (*it)->timestamp;
374 if (!agreement->second.first.IsHtSupported ()
402 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
405 if (!(*it)->hdr.IsQosData ())
407 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
409 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid && (*it)->hdr.GetSequenceNumber () == seqnumber)
413 i->second.second.erase ((*it));
451 uint32_t nPackets = 0;
453 while (queueIt != (*it).second.second.end ())
455 uint16_t currentSeq = (*queueIt).hdr.GetSequenceNumber ();
458 while (queueIt != (*it).second.second.end () && (*queueIt).hdr.GetSequenceNumber () == currentSeq)
470 uint32_t nPackets = 0;
471 uint16_t currentSeq = 0;
474 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
477 if (!(*it)->hdr.IsQosData ())
479 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
481 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
483 currentSeq = (*it)->hdr.GetSequenceNumber ();
486 while (it !=
m_retryPackets.end () && (*it)->hdr.GetSequenceNumber () == currentSeq)
518 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
522 if (!(*it)->hdr.IsQosData ())
524 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
526 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid && currentSeq == (*it)->hdr.GetSequenceNumber ())
539 uint16_t sequenceFirstLost = 0;
545 bool foundFirstLost =
false;
546 uint8_t nSuccessfulMpdus = 0;
547 uint8_t nFailedMpdus = 0;
551 if (it->second.first.m_inactivityEvent.IsRunning ())
556 it->second.first.m_inactivityEvent.Cancel ();
565 for (
PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd; )
568 (*queueIt).hdr.GetFragmentNumber ()))
572 queueIt = it->second.second.erase (queueIt);
578 foundFirstLost =
true;
579 sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber ();
580 (*it).second.first.SetStartingSequence (sequenceFirstLost);
583 if (!
AlreadyExists ((*queueIt).hdr.GetSequenceNumber (),recipient,tid))
593 for (
PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd; )
595 uint16_t currentSeq = (*queueIt).hdr.GetSequenceNumber ();
598 while (queueIt != queueEnd
599 && (*queueIt).hdr.GetSequenceNumber () == currentSeq)
607 queueIt = it->second.second.erase (queueIt);
614 foundFirstLost =
true;
615 sequenceFirstLost = (*queueIt).hdr.GetSequenceNumber ();
616 (*it).second.first.SetStartingSequence (sequenceFirstLost);
623 if (!
AlreadyExists ((*queueIt).hdr.GetSequenceNumber (),recipient,tid))
636 it->second.first.CompleteExchange ();
666 if ((*it).second.first.IsBlockAckRequestNeeded ()
668 &&
m_queue->GetNPacketsByTidAndAddress (tid, recipient) == 0))
709 it->second.first.SetStartingSequence (startingSeq);
738 nextSeq = nextSeqNumber;
740 it->second.first.NotifyMpduTransmission (nextSeq);
746 Bar request (bar, recipient, tid, it->second.first.IsImmediateBlockAck ());
747 m_bars.push_back (request);
766 uint32_t packets =
m_queue->GetNPacketsByTidAndAddress (tid, recipient) +
783 if ((seqNumber + 63) < it->second.first.GetStartingSequence ())
787 else if (it->second.first.GetTimeout () > 0 && it->second.first.m_inactivityEvent.IsExpired ())
811 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
814 if ((*it)->hdr.GetAddr1 () ==
address 815 && (*it)->hdr.GetQosTid () == tid
816 && (*it)->hdr.GetSequenceNumber () == seq)
833 if (j->second.second.empty ())
839 for (
PacketQueueI i = j->second.second.begin (); i != j->second.second.end (); i++)
849 j->second.first.GetTid (),
850 i->hdr.GetSequenceNumber ());
853 j->second.second.erase (j->second.second.begin (), end);
854 j->second.first.SetStartingSequence (end->hdr.GetSequenceNumber ());
897 std::list<PacketQueueI>::const_iterator it =
m_retryPackets.begin ();
900 if (!(*it)->hdr.IsQosData ())
902 NS_FATAL_ERROR (
"Packet in blockAck manager retry queue is not Qos Data");
904 if ((*it)->hdr.GetAddr1 () == recipient && (*it)->hdr.GetQosTid () == tid)
906 return (*it)->hdr.GetSequenceNumber ();
928 NS_LOG_INFO (
"Adding to retry queue " << (*item).hdr.GetSequenceNumber ());
937 if (((item->hdr.GetSequenceNumber () - (*it)->hdr.GetSequenceNumber () + 4096) % 4096) > 2047)
void SetUnblockDestinationCallback(Callback< void, Mac48Address, uint8_t > callback)
Set unblock destination callback.
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...
uint32_t GetNRetryNeededPackets(Mac48Address recipient, uint8_t tid) const
#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 StorePacket(Ptr< const Packet > packet, const WifiMacHeader &hdr, Time tStamp)
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...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
uint16_t GetStartingSequence(void) const
Return the starting squence number.
#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. ...
Ptr< const Packet > GetNextPacket(WifiMacHeader &hdr, bool removePacket)
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
TxOk m_txOkCallback
transmit ok callback
bool ExistsAgreementInState(Mac48Address recipient, uint8_t tid, OriginatorBlockAckAgreement::State state) const
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)
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)
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.
void NotifyAgreementUnsuccessful(Mac48Address recipient, uint8_t tid)
static TypeId GetTypeId(void)
Get the type ID.
void InsertInRetryQueue(PacketQueueI item)
std::list< PacketQueueI > m_retryPackets
This list contains all iterators to stored packets that need to be retransmitted. ...
bool ExistsAgreement(Mac48Address recipient, uint8_t tid) const
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 ...
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)
Item(Ptr< const Packet > packet, const WifiMacHeader &hdr, Time tStamp)
Constructor.
void SetState(State state)
Set the current state.
void SetTxOkCallback(TxOk callback)
std::string GetUniqueName(void) const
bool HasBar(Bar &bar)
Returns true if the BAR is scheduled.
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
Mac48Address recipient
recipient
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint16_t GetSeqNumOfNextRetryPacket(Mac48Address recipient, uint8_t tid) const
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
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Callback< void, Mac48Address, uint8_t > m_blockPackets
block packets callback
static Time Now(void)
Return the current simulation virtual time.
State
Represents the state for this agreement.
void SetBlockAckInactivityCallback(Callback< void, Mac48Address, uint8_t, bool > callback)
Set block ack inactivity callback.
bool HasHtSupported(void) const
Return whether the device has HT capability support enabled.
void SetMaxPacketDelay(Time maxDelay)
void NotifyMpduTransmission(Mac48Address recipient, uint8_t tid, uint16_t nextSeqNumber, WifiMacHeader::QosAckPolicy policy)
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
bool HasPackets(void) const
Returns true if there are packets that need of retransmission or at least a BAR is scheduled...
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
block ack type
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Ptr< const Packet > bar
block ack request
uint16_t GetNextSeqNumberByTidAndAddress(uint8_t tid, Mac48Address addr) const
Return the next sequence number for the Traffic ID and destination.
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 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.
uint8_t GetTid(void) const
Return the Traffic ID (TID).
Ptr< const Packet > packet
packet
Ptr< const Packet > PeekNextPacketByTidAndAddress(WifiMacHeader &hdr, uint8_t tid, Time *timestamp)
Peek in retransmit queue and get the next packet having address indicated by type equals to addr...
void AddHeader(const Header &header)
Add header to this packet.
Ptr< WifiMacQueue > m_queue
queue
void CompleteExchange(void)
Complete exchange function.
std::list< Item >::iterator PacketQueueI
typedef for an iterator for PacketQueue.
BlockAckType
The different block ACK policies.