From 908d87fba6d04e8e1efcb42cac36f11c3089dfe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Thu, 2 Feb 2017 19:02:01 +0100 Subject: [PATCH] wifi: (fixes #2528) Improve 802.11n RIFS support --- RELEASE_NOTES | 1 + src/wifi/model/ap-wifi-mac.cc | 28 ++++++ src/wifi/model/ap-wifi-mac.h | 8 ++ src/wifi/model/mac-low.cc | 93 ++++++++++++------- src/wifi/model/mac-low.h | 7 +- src/wifi/model/regular-wifi-mac.cc | 23 ++++- src/wifi/model/regular-wifi-mac.h | 15 +++ src/wifi/model/sta-wifi-mac.cc | 16 ++++ src/wifi/model/wifi-mac.cc | 2 +- src/wifi/model/wifi-mac.h | 4 + src/wifi/model/wifi-remote-station-manager.cc | 15 ++- src/wifi/model/wifi-remote-station-manager.h | 14 +++ 12 files changed, 187 insertions(+), 39 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 712d47e8f..bb88563e5 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -41,6 +41,7 @@ Bugs fixed - Bug 2518 - Suppress printing of list of modules for Python programs - Bug 2521 - Include ipv6-option.h in wscript - Bug 2527 - PrintRoutingTable extended to add an optional Time::Units parameter +- Bug 2528 - 802.11n RIFS cannot be enabled - Bug 2529 - Missing trace when Block ACK timeout is triggered or when missing MPDUs are announced by a Block ACK response - Bug 2530 - Rename aodv::SetBalckListTimeout to aodv::SetBlackListTimeout - Bug 2532 - Inconsistencies between 802.11n MCS and NSS value reported in TXVECTOR diff --git a/src/wifi/model/ap-wifi-mac.cc b/src/wifi/model/ap-wifi-mac.cc index e7d405a7c..35b3f7da4 100644 --- a/src/wifi/model/ap-wifi-mac.cc +++ b/src/wifi/model/ap-wifi-mac.cc @@ -68,6 +68,11 @@ ApWifiMac::GetTypeId (void) BooleanValue (true), MakeBooleanAccessor (&ApWifiMac::m_enableNonErpProtection), MakeBooleanChecker ()) + .AddAttribute ("RifsMode", "If non-HT STAs are detected, whether to force RIFS to be disabled within the BSS." + "This parameter is only used when HT is supported by the AP.", + BooleanValue (true), + MakeBooleanAccessor (&ApWifiMac::m_disableRifs), + MakeBooleanChecker ()) ; return tid; } @@ -511,6 +516,7 @@ ApWifiMac::GetHtOperation (void) const if (m_htSupported) { operation.SetHtSupported (1); + operation.SetRifsMode (GetRifsMode ()); operation.SetNonGfHtStasPresent (IsNonGfHtStasPresent ()); if (m_nonHtStations.empty ()) { @@ -1143,4 +1149,26 @@ ApWifiMac::GetUseNonErpProtection (void) const return useProtection; } +bool +ApWifiMac::GetRifsMode (void) const +{ + bool rifsMode = false; + if (m_htSupported && !m_vhtSupported) //RIFS mode is forbidden for VHT + { + if (m_nonHtStations.empty () || !m_disableRifs) + { + rifsMode = true; + } + } + if (GetRifsSupported () && rifsMode) + { + m_stationManager->SetRifsPermitted (true); + } + else + { + m_stationManager->SetRifsPermitted (false); + } + return rifsMode; +} + } //namespace ns3 diff --git a/src/wifi/model/ap-wifi-mac.h b/src/wifi/model/ap-wifi-mac.h index 67f51be20..6a1f07925 100644 --- a/src/wifi/model/ap-wifi-mac.h +++ b/src/wifi/model/ap-wifi-mac.h @@ -265,6 +265,13 @@ private: * false otherwise */ bool GetUseNonErpProtection (void) const; + /** + * Return whether RIFS is allowed in the BSS. + * + * \return true if RIFS is allowed in the BSS, + * false otherwise + */ + bool GetRifsMode (void) const; virtual void DoDispose (void); virtual void DoInitialize (void); @@ -279,6 +286,7 @@ private: std::list m_nonErpStations; //!< List of all non-ERP stations currently associated to the AP std::list m_nonHtStations; //!< List of all non-HT stations currently associated to the AP bool m_enableNonErpProtection; //!< Flag whether protection mechanism is used or not when non-ERP STAs are present within the BSS + bool m_disableRifs; //!< Flag whether to force RIFS to be disabled within the BSS If non-HT STAs are detected }; } //namespace ns3 diff --git a/src/wifi/model/mac-low.cc b/src/wifi/model/mac-low.cc index d735b7b18..3d6ee75f3 100644 --- a/src/wifi/model/mac-low.cc +++ b/src/wifi/model/mac-low.cc @@ -266,7 +266,7 @@ MacLow::MacLow () m_sendCtsEvent (), m_sendAckEvent (), m_sendDataEvent (), - m_waitSifsEvent (), + m_waitIfsEvent (), m_endTxNoAckEvent (), m_currentPacket (0), m_currentDca (0), @@ -332,9 +332,8 @@ MacLow::DoDispose (void) m_sendCtsEvent.Cancel (); m_sendAckEvent.Cancel (); m_sendDataEvent.Cancel (); - m_waitSifsEvent.Cancel (); + m_waitIfsEvent.Cancel (); m_endTxNoAckEvent.Cancel (); - m_waitRifsEvent.Cancel (); m_phy = 0; m_stationManager = 0; if (m_phyMacLowListener != 0) @@ -399,14 +398,9 @@ MacLow::CancelAllEvents (void) m_sendDataEvent.Cancel (); oneRunning = true; } - if (m_waitSifsEvent.IsRunning ()) + if (m_waitIfsEvent.IsRunning ()) { - m_waitSifsEvent.Cancel (); - oneRunning = true; - } - if (m_waitRifsEvent.IsRunning ()) - { - m_waitRifsEvent.Cancel (); + m_waitIfsEvent.Cancel (); oneRunning = true; } if (m_endTxNoAckEvent.IsRunning ()) @@ -921,13 +915,25 @@ MacLow::ReceiveOk (Ptr packet, double rxSnr, WifiTxVector txVector, bool } if (m_txParams.HasNextPacket ()) { - m_waitSifsEvent = Simulator::Schedule (GetSifs (), - &MacLow::WaitSifsAfterEndTxFragment, this); + if (m_stationManager->GetRifsPermitted ()) + { + m_waitIfsEvent = Simulator::Schedule (GetRifs (), &MacLow::WaitIfsAfterEndTxFragment, this); + } + else + { + m_waitIfsEvent = Simulator::Schedule (GetSifs (), &MacLow::WaitIfsAfterEndTxFragment, this); + } } else if (m_currentHdr.IsQosData () && m_currentDca->HasTxop ()) { - m_waitSifsEvent = Simulator::Schedule (GetSifs (), - &MacLow::WaitSifsAfterEndTxPacket, this); + if (m_stationManager->GetRifsPermitted ()) + { + m_waitIfsEvent = Simulator::Schedule (GetRifs (), &MacLow::WaitIfsAfterEndTxPacket, this); + } + else + { + m_waitIfsEvent = Simulator::Schedule (GetSifs (), &MacLow::WaitIfsAfterEndTxPacket, this); + } } m_ampdu = false; if (m_currentHdr.IsQosData ()) @@ -951,9 +957,14 @@ MacLow::ReceiveOk (Ptr packet, double rxSnr, WifiTxVector txVector, bool m_ampdu = false; if (m_currentHdr.IsQosData () && m_currentDca->HasTxop ()) { - m_waitSifsEvent = Simulator::Schedule (GetSifs (), - &MacLow::WaitSifsAfterEndTxPacket, - this); + if (m_stationManager->GetRifsPermitted ()) + { + m_waitIfsEvent = Simulator::Schedule (GetRifs (), &MacLow::WaitIfsAfterEndTxPacket, this); + } + else + { + m_waitIfsEvent = Simulator::Schedule (GetSifs (), &MacLow::WaitIfsAfterEndTxPacket, this); + } } } else if (hdr.IsBlockAckReq () && hdr.GetAddr1 () == m_self) @@ -1747,23 +1758,30 @@ MacLow::StartDataTxTimers (WifiTxVector dataTxVector) } else if (m_txParams.HasNextPacket ()) { - if (m_stationManager->HasHtSupported ()) + NS_ASSERT (m_waitIfsEvent.IsExpired ()); + Time delay = txDuration; + if (m_stationManager->GetRifsPermitted ()) { - Time delay = txDuration + GetRifs (); - NS_ASSERT (m_waitRifsEvent.IsExpired ()); - m_waitRifsEvent = Simulator::Schedule (delay, &MacLow::WaitSifsAfterEndTxFragment, this); + delay += GetRifs (); } else { - Time delay = txDuration + GetSifs (); - NS_ASSERT (m_waitSifsEvent.IsExpired ()); - m_waitSifsEvent = Simulator::Schedule (delay, &MacLow::WaitSifsAfterEndTxFragment, this); + delay += GetSifs (); } + m_waitIfsEvent = Simulator::Schedule (delay, &MacLow::WaitIfsAfterEndTxFragment, this); } else if (m_currentHdr.IsQosData () && m_currentHdr.IsQosBlockAck () && m_currentDca->HasTxop ()) { - Time delay = txDuration + GetSifs (); - m_waitSifsEvent = Simulator::Schedule (delay, &MacLow::WaitSifsAfterEndTxPacket, this); + Time delay = txDuration; + if (m_stationManager->GetRifsPermitted ()) + { + delay += GetRifs (); + } + else + { + delay += GetSifs (); + } + m_waitIfsEvent = Simulator::Schedule (delay, &MacLow::WaitIfsAfterEndTxPacket, this); } else { @@ -1805,7 +1823,14 @@ MacLow::SendDataPacket (void) } if (m_txParams.HasNextPacket ()) { - duration += GetSifs (); + if (m_stationManager->GetRifsPermitted ()) + { + duration += GetRifs (); + } + else + { + duration += GetSifs (); + } duration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (), m_currentTxVector, m_phy->GetFrequency ()); if (m_txParams.MustWaitAck ()) @@ -1998,8 +2023,14 @@ MacLow::SendDataAfterCts (Mac48Address source, Time duration) } if (m_txParams.HasNextPacket ()) { - newDuration += GetSifs (); - newDuration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (), m_currentTxVector, m_phy->GetFrequency ()); + if (m_stationManager->GetRifsPermitted ()) + { + newDuration += GetRifs (); + } + else + { + newDuration += GetSifs (); + } newDuration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (), m_currentTxVector, m_phy->GetFrequency ()); if (m_txParams.MustWaitCompressedBlockAck ()) { newDuration += GetSifs (); @@ -2035,13 +2066,13 @@ MacLow::SendDataAfterCts (Mac48Address source, Time duration) } void -MacLow::WaitSifsAfterEndTxFragment (void) +MacLow::WaitIfsAfterEndTxFragment (void) { m_currentDca->StartNextFragment (); } void -MacLow::WaitSifsAfterEndTxPacket (void) +MacLow::WaitIfsAfterEndTxPacket (void) { m_currentDca->StartNextPacket (); } diff --git a/src/wifi/model/mac-low.h b/src/wifi/model/mac-low.h index 24437f7b9..21a112d05 100644 --- a/src/wifi/model/mac-low.h +++ b/src/wifi/model/mac-low.h @@ -883,8 +883,8 @@ private: * Event handler that is usually scheduled to fired at the appropriate time * after completing transmissions. */ - void WaitSifsAfterEndTxFragment (void); - void WaitSifsAfterEndTxPacket (void); + void WaitIfsAfterEndTxFragment (void); + void WaitIfsAfterEndTxPacket (void); /** * A transmission that does not require an ACK has completed. @@ -1062,10 +1062,9 @@ private: EventId m_sendCtsEvent; //!< Event to send CTS EventId m_sendAckEvent; //!< Event to send ACK EventId m_sendDataEvent; //!< Event to send DATA - EventId m_waitSifsEvent; //!< Wait for SIFS event + EventId m_waitIfsEvent; //!< Wait for IFS event EventId m_endTxNoAckEvent; //!< Event for finishing transmission that does not require ACK EventId m_navCounterResetCtsMissed; //!< Event to reset NAV when CTS is not received - EventId m_waitRifsEvent; //!< Wait for RIFS event Ptr m_currentPacket; //!< Current packet transmitted/to be transmitted WifiMacHeader m_currentHdr; //!< Header of the current transmitted packet diff --git a/src/wifi/model/regular-wifi-mac.cc b/src/wifi/model/regular-wifi-mac.cc index 9f24ddfb9..1ed04007d 100644 --- a/src/wifi/model/regular-wifi-mac.cc +++ b/src/wifi/model/regular-wifi-mac.cc @@ -825,6 +825,19 @@ RegularWifiMac::GetShortSlotTimeSupported (void) const return m_shortSlotTimeSupported; } +void +RegularWifiMac::SetRifsSupported (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + m_rifsSupported = enable; +} + +bool +RegularWifiMac::GetRifsSupported (void) const +{ + return m_rifsSupported; +} + void RegularWifiMac::Enqueue (Ptr packet, Mac48Address to, Mac48Address from) @@ -1168,8 +1181,14 @@ RegularWifiMac::GetTypeId (void) .AddAttribute ("ShortSlotTimeSupported", "Whether or not short slot time is supported (only used by ERP APs or STAs).", BooleanValue (true), - MakeBooleanAccessor (&WifiMac::GetShortSlotTimeSupported, - &WifiMac::SetShortSlotTimeSupported), + MakeBooleanAccessor (&RegularWifiMac::GetShortSlotTimeSupported, + &RegularWifiMac::SetShortSlotTimeSupported), + MakeBooleanChecker ()) + .AddAttribute ("RifsSupported", + "Whether or not RIFS is supported (only used by HT APs or STAs).", + BooleanValue (false), + MakeBooleanAccessor (&RegularWifiMac::GetRifsSupported, + &RegularWifiMac::SetRifsSupported), MakeBooleanChecker ()) .AddAttribute ("DcaTxop", "The DcaTxop object.", diff --git a/src/wifi/model/regular-wifi-mac.h b/src/wifi/model/regular-wifi-mac.h index 3fdaa5c4a..d76cf1c83 100644 --- a/src/wifi/model/regular-wifi-mac.h +++ b/src/wifi/model/regular-wifi-mac.h @@ -137,6 +137,20 @@ public: * false otherwise. */ virtual bool GetShortSlotTimeSupported (void) const; + /** + * Enable or disable RIFS feature. + * + * \param enable true if RIFS is to be supported, + * false otherwise + */ + virtual void SetRifsSupported (bool enable); + /** + * \return whether the device supports RIFS capability. + * + * \return true if short RIFS is supported, + * false otherwise. + */ + virtual bool GetRifsSupported (void) const; /** * \return the MAC address associated to this MAC layer. @@ -598,6 +612,7 @@ private: TracedCallback m_txErrCallback; bool m_shortSlotTimeSupported; + bool m_rifsSupported; }; } //namespace ns3 diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index 232bd90c7..68a70ab8c 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -584,6 +584,14 @@ StaWifiMac::Receive (Ptr packet, const WifiMacHeader *hdr) { m_stationManager->SetUseGreenfieldProtection (false); } + if (!m_vhtSupported && GetRifsSupported () && htOperation.GetRifsMode ()) + { + m_stationManager->SetRifsPermitted (true); + } + else + { + m_stationManager->SetRifsPermitted (false); + } for (uint32_t i = 0; i < m_phy->GetNMcs (); i++) { WifiMode mcs = m_phy->GetMcs (i); @@ -808,6 +816,14 @@ StaWifiMac::Receive (Ptr packet, const WifiMacHeader *hdr) { m_stationManager->SetUseGreenfieldProtection (false); } + if (!m_vhtSupported && GetRifsSupported () && htOperation.GetRifsMode ()) + { + m_stationManager->SetRifsPermitted (true); + } + else + { + m_stationManager->SetRifsPermitted (false); + } } } if (m_vhtSupported) diff --git a/src/wifi/model/wifi-mac.cc b/src/wifi/model/wifi-mac.cc index 2f07ee08f..abd2dd19c 100644 --- a/src/wifi/model/wifi-mac.cc +++ b/src/wifi/model/wifi-mac.cc @@ -189,7 +189,7 @@ WifiMac::GetTypeId (void) MakeTimeAccessor (&WifiMac::SetPifs, &WifiMac::GetPifs), MakeTimeChecker ()) - .AddAttribute ("Rifs", "The value of the RIFS constant (not supported yet!).", + .AddAttribute ("Rifs", "The value of the RIFS constant.", TimeValue (GetDefaultRifs ()), MakeTimeAccessor (&WifiMac::SetRifs, &WifiMac::GetRifs), diff --git a/src/wifi/model/wifi-mac.h b/src/wifi/model/wifi-mac.h index c128a607a..3a954f7c6 100644 --- a/src/wifi/model/wifi-mac.h +++ b/src/wifi/model/wifi-mac.h @@ -158,6 +158,10 @@ public: * \return whether the device supports short slot time capability. */ virtual bool GetShortSlotTimeSupported (void) const = 0; + /** + * \return whether the device supports RIFS capability. + */ + virtual bool GetRifsSupported (void) const = 0; /** * \param packet the packet to send. diff --git a/src/wifi/model/wifi-remote-station-manager.cc b/src/wifi/model/wifi-remote-station-manager.cc index 1868ae82f..2564441ca 100644 --- a/src/wifi/model/wifi-remote-station-manager.cc +++ b/src/wifi/model/wifi-remote-station-manager.cc @@ -360,7 +360,8 @@ WifiRemoteStationManager::WifiRemoteStationManager () m_useNonErpProtection (false), m_useGreenfieldProtection (false), m_shortPreambleEnabled (false), - m_shortSlotTimeEnabled (false) + m_shortSlotTimeEnabled (false), + m_rifsPermitted (false) { } @@ -463,6 +464,12 @@ WifiRemoteStationManager::SetShortSlotTimeEnabled (bool enable) m_shortSlotTimeEnabled = enable; } +void +WifiRemoteStationManager::SetRifsPermitted (bool allow) +{ + m_rifsPermitted = allow; +} + bool WifiRemoteStationManager::GetShortSlotTimeEnabled (void) const { @@ -475,6 +482,12 @@ WifiRemoteStationManager::GetShortPreambleEnabled (void) const return m_shortPreambleEnabled; } +bool +WifiRemoteStationManager::GetRifsPermitted (void) const +{ + return m_rifsPermitted; +} + WifiRemoteStationManager::ProtectionMode WifiRemoteStationManager::GetProtectionMode (void) const { diff --git a/src/wifi/model/wifi-remote-station-manager.h b/src/wifi/model/wifi-remote-station-manager.h index eea589c60..50a267328 100644 --- a/src/wifi/model/wifi-remote-station-manager.h +++ b/src/wifi/model/wifi-remote-station-manager.h @@ -305,6 +305,19 @@ public: * false otherwise */ bool GetShortSlotTimeEnabled (void) const; + /** + * Permit or prohibit RIFS. + * + * \param allow permit or prohibit RIFS + */ + void SetRifsPermitted (bool allow); + /** + * Return whether the device can use RIFS. + * + * \return true if RIFS is permitted, + * false otherwise + */ + bool GetRifsPermitted (void) const; /** * Reset the station, invoked in a STA upon dis-association or in an AP upon reboot. @@ -1362,6 +1375,7 @@ private: bool m_useGreenfieldProtection; //!< flag if protection for stations that do not support HT greenfield format is enabled bool m_shortPreambleEnabled; //!< flag if short PLCP preamble is enabled bool m_shortSlotTimeEnabled; //!< flag if short slot time is enabled + bool m_rifsPermitted; //!< flag if RIFS is enabled ProtectionMode m_protectionMode; //!< Protection mode for ERP stations when non-ERP stations are detected /**