From 543cf34dccf5b2662ea4debaac13b2cdcb4e2fca Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Fri, 19 Apr 2019 20:42:45 +0200 Subject: [PATCH] wifi: Improve handling of starting sequence number of transmit window --- src/wifi/model/block-ack-manager.cc | 74 ++++++++----- src/wifi/model/block-ack-manager.h | 13 ++- src/wifi/model/mpdu-aggregator.cc | 3 +- src/wifi/model/qos-txop.cc | 166 ++++------------------------ 4 files changed, 82 insertions(+), 174 deletions(-) diff --git a/src/wifi/model/block-ack-manager.cc b/src/wifi/model/block-ack-manager.cc index b9d04d92a..4e99257df 100644 --- a/src/wifi/model/block-ack-manager.cc +++ b/src/wifi/model/block-ack-manager.cc @@ -194,6 +194,9 @@ BlockAckManager::UpdateAgreement (const MgtAddBaResponseHeader *respHdr, Mac48Ad agreement.SetBufferSize (respHdr->GetBufferSize () + 1); agreement.SetTimeout (respHdr->GetTimeout ()); agreement.SetAmsduSupport (respHdr->IsAmsduSupported ()); + // update the starting sequence number because some frames may have been sent + // under Normal Ack policy after the transmission of the ADDBA Request frame + agreement.SetStartingSequence (m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient)); if (respHdr->IsImmediateBlockAck ()) { agreement.SetImmediateBlockAck (); @@ -576,7 +579,6 @@ void BlockAckManager::NotifyGotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address recipient, double rxSnr, WifiMode txMode, double dataSnr) { NS_LOG_FUNCTION (this << blockAck << recipient << rxSnr << txMode.GetUniqueName () << dataSnr); - uint16_t sequenceFirstLost = 0; if (!blockAck->IsMultiTid ()) { uint8_t tid = blockAck->GetTidInfo (); @@ -600,72 +602,79 @@ BlockAckManager::NotifyGotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac4 this, recipient, tid); } + + uint16_t currentStartingSeq = it->second.first.GetStartingSequence (); + uint16_t currentSeq = 4096; // invalid value + if (blockAck->IsBasic ()) { for (PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd; ) { - if (blockAck->IsFragmentReceived ((*queueIt)->GetHeader ().GetSequenceNumber (), + currentSeq = (*queueIt)->GetHeader ().GetSequenceNumber (); + if (blockAck->IsFragmentReceived (currentSeq, (*queueIt)->GetHeader ().GetFragmentNumber ())) { nSuccessfulMpdus++; - RemoveFromRetryQueue (recipient, tid, (*queueIt)->GetHeader ().GetSequenceNumber ()); - queueIt = it->second.second.erase (queueIt); } - else + else if (!QosUtilsIsOldPacket (currentStartingSeq, currentSeq)) { if (!foundFirstLost) { foundFirstLost = true; - sequenceFirstLost = (*queueIt)->GetHeader ().GetSequenceNumber (); - (*it).second.first.SetStartingSequence (sequenceFirstLost); + SetStartingSequence (recipient, tid, currentSeq); } nFailedMpdus++; - if (!AlreadyExists ((*queueIt)->GetHeader ().GetSequenceNumber (), recipient, tid)) + if (!AlreadyExists (currentSeq, recipient, tid)) { InsertInRetryQueue (*queueIt); } - queueIt++; } + // in any case, this packet is no longer outstanding + queueIt = it->second.second.erase (queueIt); + } + // If all frames were acknowledged, move the transmit window past the last one + if (!foundFirstLost && currentSeq != 4096) + { + SetStartingSequence (recipient, tid, (currentSeq + 1) % 4096); } } else if (blockAck->IsCompressed () || blockAck->IsExtendedCompressed ()) { for (PacketQueueI queueIt = it->second.second.begin (); queueIt != queueEnd; ) { - uint16_t currentSeq = (*queueIt)->GetHeader ().GetSequenceNumber (); + currentSeq = (*queueIt)->GetHeader ().GetSequenceNumber (); if (blockAck->IsPacketReceived (currentSeq)) { - while (queueIt != queueEnd - && (*queueIt)->GetHeader ().GetSequenceNumber () == currentSeq) + nSuccessfulMpdus++; + if (!m_txOkCallback.IsNull ()) { - nSuccessfulMpdus++; - if (!m_txOkCallback.IsNull ()) - { - m_txOkCallback ((*queueIt)->GetHeader ()); - } - RemoveFromRetryQueue (recipient, tid, currentSeq); - queueIt = it->second.second.erase (queueIt); + m_txOkCallback ((*queueIt)->GetHeader ()); } } - else + else if (!QosUtilsIsOldPacket (currentStartingSeq, currentSeq)) { if (!foundFirstLost) { foundFirstLost = true; - sequenceFirstLost = (*queueIt)->GetHeader ().GetSequenceNumber (); - (*it).second.first.SetStartingSequence (sequenceFirstLost); + SetStartingSequence (recipient, tid, currentSeq); } nFailedMpdus++; if (!m_txFailedCallback.IsNull ()) { m_txFailedCallback ((*queueIt)->GetHeader ()); } - if (!AlreadyExists ((*queueIt)->GetHeader ().GetSequenceNumber (), recipient, tid)) + if (!AlreadyExists (currentSeq, recipient, tid)) { InsertInRetryQueue (*queueIt); } - queueIt++; } + // in any case, this packet is no longer outstanding + queueIt = it->second.second.erase (queueIt); + } + // If all frames were acknowledged, move the transmit window past the last one + if (!foundFirstLost && currentSeq != 4096) + { + SetStartingSequence (recipient, tid, (currentSeq + 1) % 4096); } } m_stationManager->ReportAmpduTxStatus (recipient, tid, nSuccessfulMpdus, nFailedMpdus, rxSnr, dataSnr); @@ -687,13 +696,26 @@ BlockAckManager::NotifyMissedBlockAck (Mac48Address recipient, uint8_t tid) AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); for (auto& item : it->second.second) { - //Queue previously transmitted packets that do not already exist in the retry queue. - //The first packet is not placed in the retry queue since it should be retransmitted by the invoker. + // Queue previously transmitted packets that do not already exist in the retry queue. if (!AlreadyExists (item->GetHeader ().GetSequenceNumber (), recipient, tid)) { InsertInRetryQueue (item); } } + // remove all packets from the queue of outstanding packets (they will be + // re-inserted if retransmitted) + it->second.second.clear (); + } +} + +void +BlockAckManager::DiscardOutstandingMpdus (Mac48Address recipient, uint8_t tid) +{ + NS_LOG_FUNCTION (this << recipient << +tid); + if (ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED)) + { + AgreementsI it = m_agreements.find (std::make_pair (recipient, tid)); + it->second.second.clear (); } } diff --git a/src/wifi/model/block-ack-manager.h b/src/wifi/model/block-ack-manager.h index 83e1588e5..117c9cfc8 100644 --- a/src/wifi/model/block-ack-manager.h +++ b/src/wifi/model/block-ack-manager.h @@ -219,14 +219,23 @@ public: * with ack policy set to Block Ack, should be placed in the retransmission queue. */ void NotifyMissedBlockAck (Mac48Address recipient, uint8_t tid); + /** + * \param recipient outstanding frames' receiver. + * \param tid Traffic ID. + * + * Discard all the outstanding MPDUs destined to the given receiver and belonging + * to the given TID. Typically, this function is called by ns3::QosTxop object + * when it gives up retransmitting either a Block Ack Request or the data frames. + */ + void DiscardOutstandingMpdus (Mac48Address recipient, uint8_t tid); /** * \param recipient Address of peer station involved in block ack mechanism. * \param tid Traffic ID. * * \return the number of packets buffered for a specified agreement * - * Returns number of packets buffered for a specified agreement. This methods doesn't return - * number of buffered MPDUs but number of buffered MSDUs. + * Returns the number of packets buffered for a specified agreement. This methods doesn't return + * the number of buffered MPDUs but the number of buffered MSDUs. */ uint32_t GetNBufferedPackets (Mac48Address recipient, uint8_t tid) const; /** diff --git a/src/wifi/model/mpdu-aggregator.cc b/src/wifi/model/mpdu-aggregator.cc index 0901bb316..1fed06332 100644 --- a/src/wifi/model/mpdu-aggregator.cc +++ b/src/wifi/model/mpdu-aggregator.cc @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Ghada Badawy + * Stefano Avallone */ #include "ns3/log.h" @@ -340,7 +341,7 @@ MpduAggregator::GetNextAmpdu (Ptr mpdu, WifiTxVector txV if (edcaIt->second->GetBaAgreementEstablished (recipient, tid)) { /* here is performed mpdu aggregation */ - uint16_t startingSequenceNumber = mpdu->GetHeader ().GetSequenceNumber (); + uint16_t startingSequenceNumber = edcaIt->second->GetBaStartingSequence (recipient, tid); Ptr nextMpdu; uint16_t maxMpdus = edcaIt->second->GetBaBufferSize (recipient, tid); uint32_t currentAmpduSize = 0; diff --git a/src/wifi/model/qos-txop.cc b/src/wifi/model/qos-txop.cc index 636bc4204..fd05e583a 100644 --- a/src/wifi/model/qos-txop.cc +++ b/src/wifi/model/qos-txop.cc @@ -765,7 +765,6 @@ QosTxop::MissedCts (void) if (!NeedRtsRetransmission (m_currentPacket, m_currentHdr)) { NS_LOG_DEBUG ("Cts Fail"); - bool resetCurrentPacket = true; m_stationManager->ReportFinalRtsFailed (m_currentHdr.GetAddr1 (), &m_currentHdr); if (!m_txFailedCallback.IsNull ()) { @@ -773,39 +772,10 @@ QosTxop::MissedCts (void) } if (GetAmpduExist (m_currentHdr.GetAddr1 ()) || m_currentHdr.IsQosData ()) { - uint8_t tid = GetTid (m_currentPacket, m_currentHdr); - - if (GetBaAgreementEstablished (m_currentHdr.GetAddr1 (), tid)) - { - NS_LOG_DEBUG ("Transmit Block Ack Request"); - CtrlBAckRequestHeader reqHdr; - reqHdr.SetType (GetBaBufferSize (m_currentHdr.GetAddr1 (), tid) > 64 ? EXTENDED_COMPRESSED_BLOCK_ACK : COMPRESSED_BLOCK_ACK); - reqHdr.SetStartingSequence (m_txMiddle->PeekNextSequenceNumberFor (&m_currentHdr)); - reqHdr.SetTidInfo (tid); - reqHdr.SetHtImmediateAck (true); - Ptr bar = Create (); - bar->AddHeader (reqHdr); - Bar request (bar, m_currentHdr.GetAddr1 (), tid, reqHdr.MustSendHtImmediateAck ()); - m_currentBar = request; - WifiMacHeader hdr; - hdr.SetType (WIFI_MAC_CTL_BACKREQ); - hdr.SetAddr1 (request.recipient); - hdr.SetAddr2 (m_low->GetAddress ()); - hdr.SetAddr3 (m_low->GetBssid ()); - hdr.SetDsNotTo (); - hdr.SetDsNotFrom (); - hdr.SetNoRetry (); - hdr.SetNoMoreFragments (); - m_currentPacket = request.bar; - m_currentHdr = hdr; - resetCurrentPacket = false; - } + m_baManager->NotifyDiscardedMpdu (Create (m_currentPacket, m_currentHdr)); } //to reset the dcf. - if (resetCurrentPacket == true) - { - m_currentPacket = 0; - } + m_currentPacket = 0; ResetCw (); m_cwTrace = GetCw (); } @@ -897,7 +867,6 @@ QosTxop::MissedAck (void) NS_LOG_DEBUG ("Ack Fail"); m_stationManager->ReportFinalDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr, m_currentPacket->GetSize ()); - bool resetCurrentPacket = true; if (!m_txFailedCallback.IsNull ()) { m_txFailedCallback (m_currentHdr); @@ -919,39 +888,9 @@ QosTxop::MissedAck (void) } if (GetAmpduExist (m_currentHdr.GetAddr1 ()) || m_currentHdr.IsQosData ()) { - uint8_t tid = GetTid (m_currentPacket, m_currentHdr); - if (GetBaAgreementEstablished (m_currentHdr.GetAddr1 (), tid)) - { - //send Block ACK Request in order to shift WinStart at the receiver - NS_LOG_DEBUG ("Transmit Block Ack Request"); - CtrlBAckRequestHeader reqHdr; - reqHdr.SetType (GetBaBufferSize (m_currentHdr.GetAddr1 (), tid) > 64 ? EXTENDED_COMPRESSED_BLOCK_ACK : COMPRESSED_BLOCK_ACK); - reqHdr.SetStartingSequence (m_txMiddle->PeekNextSequenceNumberFor (&m_currentHdr)); - reqHdr.SetTidInfo (tid); - reqHdr.SetHtImmediateAck (true); - Ptr bar = Create (); - bar->AddHeader (reqHdr); - Bar request (bar, m_currentHdr.GetAddr1 (), tid, reqHdr.MustSendHtImmediateAck ()); - m_currentBar = request; - WifiMacHeader hdr; - hdr.SetType (WIFI_MAC_CTL_BACKREQ); - hdr.SetAddr1 (request.recipient); - hdr.SetAddr2 (m_low->GetAddress ()); - hdr.SetAddr3 (m_low->GetBssid ()); - hdr.SetDsNotTo (); - hdr.SetDsNotFrom (); - hdr.SetNoRetry (); - hdr.SetNoMoreFragments (); - m_currentPacket = request.bar; - m_currentHdr = hdr; - resetCurrentPacket = false; - } - } - //to reset the dcf. - if (resetCurrentPacket == true) - { - m_currentPacket = 0; + m_baManager->NotifyDiscardedMpdu (Create (m_currentPacket, m_currentHdr)); } + m_currentPacket = 0; ResetCw (); m_cwTrace = GetCw (); } @@ -982,6 +921,11 @@ void QosTxop::MissedBlockAck (uint8_t nMpdus) { NS_LOG_FUNCTION (this << +nMpdus); + /* + * If the BlockAck frame is lost, the originator may transmit a BlockAckReq + * frame to solicit an immediate BlockAck frame or it may retransmit the Data + * frames. (IEEE std 802.11-2016 sec. 10.24.7.7 + */ uint8_t tid = GetTid (m_currentPacket, m_currentHdr); if (GetAmpduExist (m_currentHdr.GetAddr1 ())) { @@ -991,71 +935,35 @@ QosTxop::MissedBlockAck (uint8_t nMpdus) { if (NeedBarRetransmission ()) { - if (!GetAmpduExist (m_currentHdr.GetAddr1 ())) + NS_LOG_DEBUG ("Retransmit block ack request"); + if (m_currentHdr.IsBlockAckReq ()) { - //should i report this to station addressed by ADDR1? - NS_LOG_DEBUG ("Retransmit block ack request"); m_currentHdr.SetRetry (); + UpdateFailedCw (); + m_cwTrace = GetCw (); } - else + else // missed block ack after data frame with Implicit BAR Ack policy { - //standard says when losing a BlockAck originator may send a BAR page 139 - NS_LOG_DEBUG ("Transmit Block Ack Request"); - CtrlBAckRequestHeader reqHdr; - reqHdr.SetType (GetBaBufferSize (m_currentHdr.GetAddr1 (), tid) > 64 ? EXTENDED_COMPRESSED_BLOCK_ACK : COMPRESSED_BLOCK_ACK); - if (m_currentHdr.IsQosData ()) - { - reqHdr.SetStartingSequence (m_currentHdr.GetSequenceNumber ()); - } - else if (m_currentHdr.IsBlockAckReq ()) - { - CtrlBAckRequestHeader baReqHdr; - m_currentPacket->PeekHeader (baReqHdr); - reqHdr.SetStartingSequence (baReqHdr.GetStartingSequence ()); - } - else if (m_currentHdr.IsBlockAck ()) - { - CtrlBAckResponseHeader baRespHdr; - m_currentPacket->PeekHeader (baRespHdr); - reqHdr.SetStartingSequence (m_currentHdr.GetSequenceNumber ()); - } - reqHdr.SetTidInfo (tid); - reqHdr.SetHtImmediateAck (true); - Ptr bar = Create (); - bar->AddHeader (reqHdr); - Bar request (bar, m_currentHdr.GetAddr1 (), tid, reqHdr.MustSendHtImmediateAck ()); - m_currentBar = request; - WifiMacHeader hdr; - hdr.SetType (WIFI_MAC_CTL_BACKREQ); - hdr.SetAddr1 (request.recipient); - hdr.SetAddr2 (m_low->GetAddress ()); - hdr.SetAddr3 (m_low->GetBssid ()); - hdr.SetDsNotTo (); - hdr.SetDsNotFrom (); - hdr.SetNoRetry (); - hdr.SetNoMoreFragments (); - - m_currentPacket = request.bar; - m_currentHdr = hdr; + m_baManager->ScheduleBlockAckReq (m_currentHdr.GetAddr1 (), tid); + m_currentPacket = 0; } - UpdateFailedCw (); - m_cwTrace = GetCw (); } else { NS_LOG_DEBUG ("Block Ack Request Fail"); //to reset the dcf. + m_baManager->DiscardOutstandingMpdus (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr)); m_currentPacket = 0; ResetCw (); m_cwTrace = GetCw (); } } - else //implicit BAR + else { + // implicit BAR and do not use BAR after missed block ack, hence try to retransmit data frames if (!NeedDataRetransmission (m_currentPacket, m_currentHdr)) { NS_LOG_DEBUG ("Block Ack Fail"); - bool resetCurrentPacket = true; if (!m_txFailedCallback.IsNull ()) { m_txFailedCallback (m_currentHdr); @@ -1075,41 +983,9 @@ QosTxop::MissedBlockAck (uint8_t nMpdus) } } } - if (GetAmpduExist (m_currentHdr.GetAddr1 ()) || m_currentHdr.IsQosData ()) - { - uint8_t tid = GetTid (m_currentPacket, m_currentHdr); - if (GetBaAgreementEstablished (m_currentHdr.GetAddr1 (), tid)) - { - //send Block ACK Request in order to shift WinStart at the receiver - NS_LOG_DEBUG ("Transmit Block Ack Request"); - CtrlBAckRequestHeader reqHdr; - reqHdr.SetType (GetBaBufferSize (m_currentHdr.GetAddr1 (), tid) > 64 ? EXTENDED_COMPRESSED_BLOCK_ACK : COMPRESSED_BLOCK_ACK); - reqHdr.SetStartingSequence (m_txMiddle->PeekNextSequenceNumberFor (&m_currentHdr)); - reqHdr.SetTidInfo (tid); - reqHdr.SetHtImmediateAck (true); - Ptr bar = Create (); - bar->AddHeader (reqHdr); - Bar request (bar, m_currentHdr.GetAddr1 (), tid, reqHdr.MustSendHtImmediateAck ()); - m_currentBar = request; - WifiMacHeader hdr; - hdr.SetType (WIFI_MAC_CTL_BACKREQ); - hdr.SetAddr1 (request.recipient); - hdr.SetAddr2 (m_low->GetAddress ()); - hdr.SetAddr3 (m_low->GetBssid ()); - hdr.SetDsNotTo (); - hdr.SetDsNotFrom (); - hdr.SetNoRetry (); - hdr.SetNoMoreFragments (); - m_currentPacket = request.bar; - m_currentHdr = hdr; - resetCurrentPacket = false; - } - } //to reset the dcf. - if (resetCurrentPacket == true) - { - m_currentPacket = 0; - } + m_baManager->DiscardOutstandingMpdus (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr)); + m_currentPacket = 0; ResetCw (); m_cwTrace = GetCw (); }