From 7d9079623f161ec7a359268744a1102c8d09e151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Sun, 29 Jan 2017 23:06:36 +0100 Subject: [PATCH] wifi: (fixes #2604) Use SIFS between QoS frames with Block Ack policy that belong to the same TXOP --- RELEASE_NOTES | 1 + src/wifi/model/dca-txop.cc | 2 +- src/wifi/model/dca-txop.h | 4 +- src/wifi/model/edca-txop-n.cc | 83 +++++++++++++++++++++-------------- src/wifi/model/edca-txop-n.h | 2 +- src/wifi/model/mac-low.cc | 21 ++++++--- src/wifi/model/mac-low.h | 2 +- 7 files changed, 73 insertions(+), 42 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index e27f49dd8..643a51526 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -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 diff --git a/src/wifi/model/dca-txop.cc b/src/wifi/model/dca-txop.cc index 6f1456649..dc1e648f1 100644 --- a/src/wifi/model/dca-txop.cc +++ b/src/wifi/model/dca-txop.cc @@ -582,7 +582,7 @@ DcaTxop::IsEdca () } void -DcaTxop::StartNext (void) +DcaTxop::StartNextPacket (void) { NS_LOG_WARN ("StartNext should not be called for non QoS!"); } diff --git a/src/wifi/model/dca-txop.h b/src/wifi/model/dca-txop.h index 566121f8d..2502fd812 100644 --- a/src/wifi/model/dca-txop.h +++ b/src/wifi/model/dca-txop.h @@ -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); diff --git a/src/wifi/model/edca-txop-n.cc b/src/wifi/model/edca-txop-n.cc index ab959fc6c..f7e8d38b8 100644 --- a/src/wifi/model/edca-txop-n.cc +++ b/src/wifi/model/edca-txop-n.cc @@ -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 peekedPacket = m_queue->PeekByTidAndAddress (&hdr, - m_currentHdr.GetQosTid (), - WifiMacHeader::ADDR1, - m_currentHdr.GetAddr1 (), - &tstamp); + Ptr 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 diff --git a/src/wifi/model/edca-txop-n.h b/src/wifi/model/edca-txop-n.h index 8b1297407..ebbee65c9 100644 --- a/src/wifi/model/edca-txop-n.h +++ b/src/wifi/model/edca-txop-n.h @@ -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. */ diff --git a/src/wifi/model/mac-low.cc b/src/wifi/model/mac-low.cc index d2531ad2a..d735b7b18 100644 --- a/src/wifi/model/mac-low.cc +++ b/src/wifi/model/mac-low.cc @@ -924,10 +924,10 @@ MacLow::ReceiveOk (Ptr 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, 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 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 diff --git a/src/wifi/model/mac-low.h b/src/wifi/model/mac-low.h index 753014cf5..24437f7b9 100644 --- a/src/wifi/model/mac-low.h +++ b/src/wifi/model/mac-low.h @@ -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.