diff --git a/src/wifi/model/frame-exchange-manager.cc b/src/wifi/model/frame-exchange-manager.cc index 462bf0912..62b5c30e4 100644 --- a/src/wifi/model/frame-exchange-manager.cc +++ b/src/wifi/model/frame-exchange-manager.cc @@ -994,6 +994,25 @@ FrameExchangeManager::NotifyChannelReleased(Ptr txop) m_protectedStas.clear(); } +Ptr +FrameExchangeManager::DropMpduIfRetryLimitReached(Ptr psdu) +{ + NS_LOG_FUNCTION(this << *psdu); + + const auto mpdusToDrop = GetWifiRemoteStationManager()->GetMpdusToDropOnTxFailure(psdu); + Ptr droppedMpdu{nullptr}; + + for (const auto& mpdu : mpdusToDrop) + { + // this MPDU needs to be dropped + droppedMpdu = mpdu; + NotifyPacketDiscarded(mpdu); + DequeueMpdu(mpdu); + } + + return droppedMpdu; +} + void FrameExchangeManager::NormalAckTimeout(Ptr mpdu, const WifiTxVector& txVector) { diff --git a/src/wifi/model/frame-exchange-manager.h b/src/wifi/model/frame-exchange-manager.h index f531254e7..8833a0b1f 100644 --- a/src/wifi/model/frame-exchange-manager.h +++ b/src/wifi/model/frame-exchange-manager.h @@ -652,6 +652,17 @@ class FrameExchangeManager : public Object */ virtual void TransmissionFailed(); + /** + * Wrapper for the GetMpdusToDropOnTxFailure function of the remote station manager that + * additionally drops the MPDUs in the given PSDU that the remote station manager requested + * to drop. + * + * @param psdu the given PSDU + * @return an MPDU that has been dropped, if any, to be notified to the remote station manager + * through the appropriate function + */ + Ptr DropMpduIfRetryLimitReached(Ptr psdu); + /** * Called when the Ack timeout expires. * diff --git a/src/wifi/model/wifi-remote-station-manager.cc b/src/wifi/model/wifi-remote-station-manager.cc index c619659a5..8af3363c3 100644 --- a/src/wifi/model/wifi-remote-station-manager.cc +++ b/src/wifi/model/wifi-remote-station-manager.cc @@ -15,6 +15,7 @@ #include "wifi-mpdu.h" #include "wifi-net-device.h" #include "wifi-phy.h" +#include "wifi-psdu.h" #include "wifi-tx-parameters.h" #include "ns3/boolean.h" @@ -57,6 +58,17 @@ WifiRemoteStationManager::GetTypeId() UintegerValue(4), MakeUintegerAccessor(&WifiRemoteStationManager::SetMaxSlrc), MakeUintegerChecker()) + .AddAttribute( + "IncrementRetryCountUnderBa", + "The 802.11-2020 standard states that the retry count for frames that are part of " + "a Block Ack agreement shall not be incremented when a transmission fails. As a " + "consequence, frames that are part of a Block Ack agreement are not dropped based " + "on the number of retries. Set this attribute to true to override the standard " + "behavior and increment the retry count (and eventually drop) frames that are " + "part of a Block Ack agreement.", + BooleanValue(false), + MakeBooleanAccessor(&WifiRemoteStationManager::m_incrRetryCountUnderBa), + MakeBooleanChecker()) .AddAttribute("RtsCtsThreshold", "If the size of the PSDU is bigger than this value, we use an RTS/CTS " "handshake before sending the data frame." @@ -1110,6 +1122,63 @@ WifiRemoteStationManager::ReportAmpduTxStatus(Mac48Address address, dataTxVector.GetNss(GetStaId(address, dataTxVector))); } +std::list> +WifiRemoteStationManager::GetMpdusToDropOnTxFailure(Ptr psdu) +{ + NS_LOG_FUNCTION(this << *psdu); + + auto* station = Lookup(psdu->GetHeader(0).GetAddr1()); + + DoIncrementRetryCountOnTxFailure(station, psdu); + return DoGetMpdusToDropOnTxFailure(station, psdu); +} + +void +WifiRemoteStationManager::DoIncrementRetryCountOnTxFailure(WifiRemoteStation* station, + Ptr psdu) +{ + NS_LOG_FUNCTION(this << *psdu); + + // The frame retry count for an MSDU or A-MSDU that is not part of a block ack agreement or + // for an MMPDU shall be incremented every time transmission fails for that MSDU, A-MSDU, or + // MMPDU, including of an associated RTS (Sec. 10.23.2.12.1 of 802.11-2020). + // Frames for which the retry count needs to be incremented: + // - management frames + // - non-QoS Data frames + // - QoS Data frames that are not part of a Block Ack agreement + // - QoS Data frames that are part of a Block Ack agreement if the IncrementRetryCountUnderBa + // attribute is set to true + const auto& hdr = psdu->GetHeader(0); + + if (hdr.IsMgt() || (hdr.IsData() && !hdr.IsQosData()) || + (hdr.IsQosData() && (!m_wifiMac->GetBaAgreementEstablishedAsOriginator( + hdr.GetAddr1(), + hdr.GetQosTid() || m_incrRetryCountUnderBa)))) + { + psdu->IncrementRetryCount(); + } +} + +std::list> +WifiRemoteStationManager::DoGetMpdusToDropOnTxFailure(WifiRemoteStation* station, + Ptr psdu) +{ + NS_LOG_FUNCTION(this << *psdu); + + std::list> mpdusToDrop; + + for (const auto& mpdu : *PeekPointer(psdu)) + { + if (mpdu->GetRetryCount() == m_wifiMac->GetFrameRetryLimit()) + { + // this MPDU needs to be dropped + mpdusToDrop.push_back(mpdu); + } + } + + return mpdusToDrop; +} + bool WifiRemoteStationManager::NeedRts(const WifiMacHeader& header, const WifiTxParameters& txParams) { diff --git a/src/wifi/model/wifi-remote-station-manager.h b/src/wifi/model/wifi-remote-station-manager.h index 7a285e6ef..d2a4d5328 100644 --- a/src/wifi/model/wifi-remote-station-manager.h +++ b/src/wifi/model/wifi-remote-station-manager.h @@ -26,6 +26,7 @@ #include "ns3/vht-capabilities.h" #include +#include #include #include #include @@ -38,6 +39,7 @@ class WifiMac; class WifiMacHeader; class Packet; class WifiMpdu; +class WifiPsdu; class WifiTxVector; class WifiTxParameters; @@ -975,6 +977,15 @@ class WifiRemoteStationManager : public Object */ void ReportRxOk(Mac48Address address, RxSignalInfo rxSignalInfo, const WifiTxVector& txVector); + /** + * Increment the retry count for all the MPDUs (if needed) in the given PSDU and find the + * MPDUs to drop based on the frame retry count. + * + * @param psdu the given PSDU, whose transmission failed + * @return the list of MPDUs that have to be dropped + */ + std::list> GetMpdusToDropOnTxFailure(Ptr psdu); + /** * @param header MAC header of the data frame to send * @param txParams the TX parameters for the data frame to send @@ -1277,7 +1288,9 @@ class WifiRemoteStationManager : public Object */ uint8_t GetNess(const WifiRemoteStation* station) const; - uint8_t m_linkId; //!< the ID of the link this object is associated with + uint8_t m_linkId; //!< the ID of the link this object is associated with + bool m_incrRetryCountUnderBa; //!< whether to increment the retry count of frames that are + //!< part of a Block Ack agreement private: /** @@ -1291,6 +1304,25 @@ class WifiRemoteStationManager : public Object */ uint16_t GetStaId(Mac48Address address, const WifiTxVector& txVector) const; + /** + * Increment the retry count (if needed) for the given PSDU, whose transmission failed. + * + * @param station the station the PSDU is addressed to + * @param psdu the given PSDU + */ + virtual void DoIncrementRetryCountOnTxFailure(WifiRemoteStation* station, Ptr psdu); + + /** + * Find the MPDUs to drop (possibly based on their frame retry count) in the given PSDU, + * whose transmission failed. + * + * @param station the station the PSDU is addressed to + * @param psdu the given PSDU + * @return the MPDUs in the PSDU to drop + */ + virtual std::list> DoGetMpdusToDropOnTxFailure(WifiRemoteStation* station, + Ptr psdu); + /** * @param station the station that we need to communicate * @param size the size of the frame to send in bytes