wifi: Improve handling of starting sequence number of transmit window
This commit is contained in:
@@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user