wifi: (fixes #2604) Use SIFS between QoS frames with Block Ack policy that belong to the same TXOP
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -582,7 +582,7 @@ DcaTxop::IsEdca ()
|
||||
}
|
||||
|
||||
void
|
||||
DcaTxop::StartNext (void)
|
||||
DcaTxop::StartNextPacket (void)
|
||||
{
|
||||
NS_LOG_WARN ("StartNext should not be called for non QoS!");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user