From 8612d07e8b5558e9f1c9034ca062ee22366b3c2a Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Tue, 9 Apr 2019 17:07:48 +0200 Subject: [PATCH] wifi: Handle packets ack'ed with Normal Ack under BA agreement --- src/wifi/model/block-ack-manager.cc | 70 +++++++++++++++++++++++++++++ src/wifi/model/block-ack-manager.h | 18 ++++++++ src/wifi/model/qos-txop.cc | 14 ++++++ 3 files changed, 102 insertions(+) diff --git a/src/wifi/model/block-ack-manager.cc b/src/wifi/model/block-ack-manager.cc index a2e6d5188..476a89182 100644 --- a/src/wifi/model/block-ack-manager.cc +++ b/src/wifi/model/block-ack-manager.cc @@ -502,6 +502,76 @@ BlockAckManager::AlreadyExists (uint16_t currentSeq, Mac48Address recipient, uin return false; } +void +BlockAckManager::NotifyGotAck (Ptr mpdu) +{ + NS_LOG_FUNCTION (this << *mpdu); + NS_ASSERT (mpdu->GetHeader ().IsQosData ()); + + Mac48Address recipient = mpdu->GetHeader ().GetAddr1 (); + uint8_t tid = mpdu->GetHeader ().GetQosTid (); + NS_ASSERT (ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED)); + + AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); + NS_ASSERT (it != m_agreements.end ()); + + // remove the acknowledged frame from the queue of outstanding packets + PacketQueueI queueIt = it->second.second.begin (); + while (queueIt != it->second.second.end ()) + { + if ((*queueIt)->GetHeader ().GetSequenceNumber () == mpdu->GetHeader ().GetSequenceNumber ()) + { + queueIt = it->second.second.erase (queueIt); + } + else + { + queueIt++; + } + } + + uint16_t startingSeq = it->second.first.GetStartingSequence (); + if (mpdu->GetHeader ().GetSequenceNumber () == startingSeq) + { + // make the transmit window advance + it->second.first.SetStartingSequence ((startingSeq + 1) % 4096); + } +} + +void +BlockAckManager::NotifyMissedAck (Ptr mpdu) +{ + NS_LOG_FUNCTION (this << *mpdu); + NS_ASSERT (mpdu->GetHeader ().IsQosData ()); + + Mac48Address recipient = mpdu->GetHeader ().GetAddr1 (); + uint8_t tid = mpdu->GetHeader ().GetQosTid (); + NS_ASSERT (ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED)); + + AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); + NS_ASSERT (it != m_agreements.end ()); + + // remove the frame from the queue of outstanding packets (it will be re-inserted + // if retransmitted) + PacketQueueI queueIt = it->second.second.begin (); + while (queueIt != it->second.second.end ()) + { + if ((*queueIt)->GetHeader ().GetSequenceNumber () == mpdu->GetHeader ().GetSequenceNumber ()) + { + queueIt = it->second.second.erase (queueIt); + } + else + { + queueIt++; + } + } + + // insert in the retransmission queue + if (!AlreadyExists (mpdu->GetHeader ().GetSequenceNumber (), recipient, tid)) + { + InsertInRetryQueue (mpdu); + } +} + void BlockAckManager::NotifyGotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, WifiMode txMode, double dataSnr) { diff --git a/src/wifi/model/block-ack-manager.h b/src/wifi/model/block-ack-manager.h index fcf92d29c..76cf3be8d 100644 --- a/src/wifi/model/block-ack-manager.h +++ b/src/wifi/model/block-ack-manager.h @@ -179,6 +179,24 @@ public: * false otherwise */ bool HasPackets (void) const; + /** + * Invoked upon receipt of an ack frame after the transmission of a QoS data frame + * sent under an established Block Ack agreement. Remove the acknowledged frame + * from the outstanding packets and update the starting sequence number of the + * transmit window, if needed. + * + * \param mpdu The acknowledged MPDU. + */ + void NotifyGotAck (Ptr mpdu); + /** + * Invoked upon missed reception of an ack frame after the transmission of a + * QoS data frame sent under an established Block Ack agreement. Remove the + * acknowledged frame from the outstanding packets and insert it in the + * retransmission queue. + * + * \param mpdu The unacknowledged MPDU. + */ + void NotifyMissedAck (Ptr mpdu); /** * \param blockAck The received block ack frame. * \param recipient Sender of block ack frame. diff --git a/src/wifi/model/qos-txop.cc b/src/wifi/model/qos-txop.cc index ca9fc59d2..636bc4204 100644 --- a/src/wifi/model/qos-txop.cc +++ b/src/wifi/model/qos-txop.cc @@ -872,6 +872,12 @@ QosTxop::GotAck (void) } } } + if (m_currentHdr.IsQosData () && GetBaAgreementEstablished (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())) + { + // notify the BA manager that the current packet was acknowledged + m_baManager->NotifyGotAck (Create (m_currentPacket, m_currentHdr, + m_currentPacketTimestamp)); + } m_currentPacket = 0; ResetCw (); } @@ -955,6 +961,14 @@ QosTxop::MissedAck (void) m_stationManager->ReportDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr, m_currentPacket->GetSize ()); m_currentHdr.SetRetry (); + if (m_currentHdr.IsQosData () && GetBaAgreementEstablished (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())) + { + // notify the BA manager that the current packet was not acknowledged + m_baManager->NotifyMissedAck (Create (m_currentPacket, m_currentHdr, + m_currentPacketTimestamp)); + // let the BA manager handle its retransmission + m_currentPacket = 0; + } UpdateFailedCw (); m_cwTrace = GetCw (); }