wifi: (fixes #2604) Use SIFS between QoS frames with Block Ack policy that belong to the same TXOP

This commit is contained in:
Sébastien Deronne
2017-01-29 23:06:36 +01:00
parent d57ea266fc
commit 7d9079623f
7 changed files with 73 additions and 42 deletions

View File

@@ -67,6 +67,7 @@ Bugs fixed
- Bug 2591 - 802.11e Block Ack mechanism cannot be enabled on HT/VHT stations
- Bug 2594 - vht-wifi-network provides very low throughtput at MCS 6, 160 MHz, SGI
- Bug 2601 - HT stations should use 40 MHz channel width if the configured channel width is set to 80 or 160 MHz
- Bug 2604 - QosData frames with Block Ack policy should be separated by SIFS as long as they belong to the same TXOP
- Bug 2605 - A HT/VHT station transmitting to a legacy access point results in a null throughput
- Bug 2607 - Minstrel HT manager results in an endless loop when a 802.11ac station is transmitting to a 802.11a access point
- Bug 2614 - RIP header version should be set to 2

View File

@@ -582,7 +582,7 @@ DcaTxop::IsEdca ()
}
void
DcaTxop::StartNext (void)
DcaTxop::StartNextPacket (void)
{
NS_LOG_WARN ("StartNext should not be called for non QoS!");
}

View File

@@ -243,7 +243,7 @@ public:
/**
* Start transmission for the next packet if allowed by the TxopLimit.
*/
virtual void StartNext (void);
virtual void StartNextPacket (void);
/**
* Event handler when a transmission that
* does not require an ACK has completed.
@@ -272,7 +272,7 @@ public:
protected:
friend class DcfState;
virtual void DoDispose (void);
virtual void DoInitialize (void);

View File

@@ -791,19 +791,28 @@ EdcaTxopN::NeedBarRetransmission (void)
}
void
EdcaTxopN::StartNext (void)
EdcaTxopN::StartNextPacket (void)
{
NS_LOG_FUNCTION (this);
Time txopLimit = GetTxopLimit ();
NS_ASSERT (txopLimit == NanoSeconds (0) || Simulator::Now () - m_startTxop <= txopLimit);
WifiMacHeader hdr;
WifiMacHeader hdr = m_currentHdr;
Time tstamp;
Ptr<const Packet> peekedPacket = m_queue->PeekByTidAndAddress (&hdr,
m_currentHdr.GetQosTid (),
WifiMacHeader::ADDR1,
m_currentHdr.GetAddr1 (),
&tstamp);
Ptr<const Packet> peekedPacket = m_baManager->GetNextPacket (hdr);
if (peekedPacket == 0)
{
peekedPacket = m_queue->PeekByTidAndAddress (&hdr,
m_currentHdr.GetQosTid (),
WifiMacHeader::ADDR1,
m_currentHdr.GetAddr1 (),
&tstamp);
}
if ((m_currentHdr.IsQosBlockAck () && peekedPacket == 0) || m_baManager->HasBar (m_currentBar))
{
SendBlockAckRequest (m_currentBar);
return;
}
else if (peekedPacket == 0)
{
if (txopLimit > NanoSeconds (0))
{
@@ -812,9 +821,9 @@ EdcaTxopN::StartNext (void)
}
return;
}
MacLowTransmissionParameters params;
params.DisableOverrideDurationId ();
params.DisableNextData ();
if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck ())
{
params.DisableAck ();
@@ -823,17 +832,6 @@ EdcaTxopN::StartNext (void)
{
params.EnableAck ();
}
WifiTxVector dataTxVector = m_stationManager->GetDataTxVector (m_currentHdr.GetAddr1 (), &m_currentHdr, peekedPacket);
if (m_stationManager->NeedRts (m_currentHdr.GetAddr1 (), &m_currentHdr, peekedPacket, dataTxVector))
{
params.EnableRts ();
}
else
{
params.DisableRts ();
}
if (txopLimit >= GetLow ()->CalculateOverallTxTime (peekedPacket, &hdr, params))
{
NS_LOG_DEBUG ("start next packet");
@@ -841,7 +839,21 @@ EdcaTxopN::StartNext (void)
m_currentHdr.GetQosTid (),
WifiMacHeader::ADDR1,
m_currentHdr.GetAddr1 ());
m_currentHdr = hdr;
NS_ASSERT (m_currentPacket != 0);
uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&m_currentHdr);
m_currentHdr.SetSequenceNumber (sequence);
m_stationManager->UpdateFragmentationThreshold ();
m_currentHdr.SetFragmentNumber (0);
m_currentHdr.SetNoMoreFragments ();
m_currentHdr.SetNoRetry ();
m_fragmentNumber = 0;
VerifyBlockAck ();
GetLow ()->StartTransmission (m_currentPacket, &m_currentHdr, params, this);
if (!GetAmpduExist (m_currentHdr.GetAddr1 ()))
{
CompleteTx ();
}
}
else if (txopLimit > NanoSeconds (0))
{
@@ -894,17 +906,13 @@ EdcaTxopN::HasTxop (void) const
params.EnableAck ();
}
WifiTxVector dataTxVector = m_stationManager->GetDataTxVector (m_currentHdr.GetAddr1 (), &m_currentHdr, peekedPacket);
if (m_stationManager->NeedRts (m_currentHdr.GetAddr1 (), &m_currentHdr, peekedPacket, dataTxVector))
Time duration = GetLow ()->CalculateOverallTxTime (peekedPacket, &hdr, params);
if (m_currentPacket != 0)
{
params.EnableRts ();
//take into account current transmission in duration
duration += GetLow ()->CalculateOverallTxTime (m_currentPacket, &m_currentHdr, params);
}
else
{
params.DisableRts ();
}
return (GetTxopRemaining () >= m_low->CalculateOverallTxTime (peekedPacket, &hdr, params));
return (GetTxopRemaining () >= duration);
}
void
@@ -912,6 +920,10 @@ EdcaTxopN::EndTxNoAck (void)
{
NS_LOG_FUNCTION (this);
NS_LOG_DEBUG ("a transmission that did not require an ACK just finished");
if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck () && GetTxopLimit () > NanoSeconds (0))
{
m_txopTrace (m_startTxop, Simulator::Now () - m_startTxop);
}
m_currentPacket = 0;
m_dcf->ResetCw ();
m_cwTrace = m_dcf->GetCw ();
@@ -1066,10 +1078,17 @@ EdcaTxopN::GotBlockAck (const CtrlBAckResponseHeader *blockAck, Mac48Address rec
}
m_currentPacket = 0;
m_dcf->ResetCw ();
m_cwTrace = m_dcf->GetCw ();
m_backoffTrace = m_rng->GetNext (0, m_dcf->GetCw ());
m_dcf->StartBackoffNow (m_backoffTrace);
RestartAccessIfNeeded ();
if (!HasTxop ())
{
if (m_currentHdr.IsQosData () && GetTxopLimit () > NanoSeconds (0))
{
m_txopTrace (m_startTxop, Simulator::Now () - m_startTxop);
}
m_cwTrace = m_dcf->GetCw ();
m_backoffTrace = m_rng->GetNext (0, m_dcf->GetCw ());
m_dcf->StartBackoffNow (m_backoffTrace);
RestartAccessIfNeeded ();
}
}
void

View File

@@ -214,7 +214,7 @@ public:
/**
* Start transmission for the next packet if allowed by the TxopLimit.
*/
void StartNext (void);
void StartNextPacket (void);
/**
* Event handler when a transmission that does not require an ACK has completed.
*/

View File

@@ -924,10 +924,10 @@ MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, bool
m_waitSifsEvent = Simulator::Schedule (GetSifs (),
&MacLow::WaitSifsAfterEndTxFragment, this);
}
else if (m_currentHdr.IsQosData () && !m_ampdu && m_currentDca->HasTxop ())
else if (m_currentHdr.IsQosData () && m_currentDca->HasTxop ())
{
m_waitSifsEvent = Simulator::Schedule (GetSifs (),
&MacLow::WaitSifsAfterEndTx, this);
&MacLow::WaitSifsAfterEndTxPacket, this);
}
m_ampdu = false;
if (m_currentHdr.IsQosData ())
@@ -949,6 +949,12 @@ MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, bool
NotifyAckTimeoutResetNow ();
m_currentDca->GotBlockAck (&blockAck, hdr.GetAddr2 (), rxSnr, txVector.GetMode (), tag.Get ());
m_ampdu = false;
if (m_currentHdr.IsQosData () && m_currentDca->HasTxop ())
{
m_waitSifsEvent = Simulator::Schedule (GetSifs (),
&MacLow::WaitSifsAfterEndTxPacket,
this);
}
}
else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self)
{
@@ -1294,9 +1300,9 @@ MacLow::CalculateOverallTxTime (Ptr<const Packet> packet,
WifiTxVector dataTxVector = GetDataTxVector (packet, hdr);
uint32_t dataSize = GetSize (packet, hdr);
txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, m_phy->GetFrequency ());
txTime += GetSifs ();
if (params.MustWaitAck ())
{
txTime += GetSifs ();
txTime += GetAckDuration (hdr->GetAddr1 (), dataTxVector);
}
return txTime;
@@ -1754,6 +1760,11 @@ MacLow::StartDataTxTimers (WifiTxVector dataTxVector)
m_waitSifsEvent = Simulator::Schedule (delay, &MacLow::WaitSifsAfterEndTxFragment, this);
}
}
else if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck () && m_currentDca->HasTxop ())
{
Time delay = txDuration + GetSifs ();
m_waitSifsEvent = Simulator::Schedule (delay, &MacLow::WaitSifsAfterEndTxPacket, this);
}
else
{
// since we do not expect any timer to be triggered.
@@ -2030,9 +2041,9 @@ MacLow::WaitSifsAfterEndTxFragment (void)
}
void
MacLow::WaitSifsAfterEndTx (void)
MacLow::WaitSifsAfterEndTxPacket (void)
{
m_currentDca->StartNext ();
m_currentDca->StartNextPacket ();
}
void

View File

@@ -884,7 +884,7 @@ private:
* after completing transmissions.
*/
void WaitSifsAfterEndTxFragment (void);
void WaitSifsAfterEndTx (void);
void WaitSifsAfterEndTxPacket (void);
/**
* A transmission that does not require an ACK has completed.