wifi: Improve handling of starting sequence number of transmit window

This commit is contained in:
Stefano Avallone
2019-04-19 20:42:45 +02:00
parent 552327c458
commit 543cf34dcc
4 changed files with 82 additions and 174 deletions

View File

@@ -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 ();
}
}

View File

@@ -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;
/**

View File

@@ -16,6 +16,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Ghada Badawy <gbadawy@gmail.com>
* Stefano Avallone <stavallo@unina.it>
*/
#include "ns3/log.h"
@@ -340,7 +341,7 @@ MpduAggregator::GetNextAmpdu (Ptr<const WifiMacQueueItem> 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<WifiMacQueueItem> nextMpdu;
uint16_t maxMpdus = edcaIt->second->GetBaBufferSize (recipient, tid);
uint32_t currentAmpduSize = 0;

View File

@@ -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<Packet> bar = Create<Packet> ();
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<const WifiMacQueueItem> (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<Packet> bar = Create<Packet> ();
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<const WifiMacQueueItem> (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<Packet> bar = Create<Packet> ();
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<Packet> bar = Create<Packet> ();
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 ();
}