From 0816eebc291752e3d0d4ec6a14977afb3265ce63 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Thu, 14 Apr 2022 09:35:37 +0200 Subject: [PATCH] wifi: Enable protection for DL MU PPDUs including one PSDU --- src/wifi/model/frame-exchange-manager.cc | 40 ++++++++++------ src/wifi/model/frame-exchange-manager.h | 7 +++ .../model/he/he-frame-exchange-manager.cc | 46 ++++++++++++++++++- src/wifi/model/he/he-frame-exchange-manager.h | 1 + .../model/ht/ht-frame-exchange-manager.cc | 32 +------------ 5 files changed, 81 insertions(+), 45 deletions(-) diff --git a/src/wifi/model/frame-exchange-manager.cc b/src/wifi/model/frame-exchange-manager.cc index 3629a1176..ddefed479 100644 --- a/src/wifi/model/frame-exchange-manager.cc +++ b/src/wifi/model/frame-exchange-manager.cc @@ -810,28 +810,42 @@ FrameExchangeManager::CtsTimeout (Ptr rts, const WifiTxVector& { NS_LOG_FUNCTION (this << *rts << txVector); - m_mac->GetWifiRemoteStationManager ()->ReportRtsFailed (m_mpdu->GetHeader ()); + DoCtsTimeout (Create (m_mpdu, true)); + m_mpdu = nullptr; +} - if (!m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (m_mpdu)) +void +FrameExchangeManager::DoCtsTimeout (Ptr psdu) +{ + NS_LOG_FUNCTION (this << *psdu); + + m_mac->GetWifiRemoteStationManager ()->ReportRtsFailed (psdu->GetHeader (0)); + + if (!m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (*psdu->begin ())) { - NS_LOG_DEBUG ("Missed CTS, discard MPDU"); - // Dequeue the MPDU if it is stored in a queue - DequeueMpdu (m_mpdu); - NotifyPacketDiscarded (m_mpdu); - m_mac->GetWifiRemoteStationManager ()->ReportFinalRtsFailed (m_mpdu->GetHeader ()); + NS_LOG_DEBUG ("Missed CTS, discard MPDU(s)"); + m_mac->GetWifiRemoteStationManager ()->ReportFinalRtsFailed (psdu->GetHeader (0)); + for (const auto& mpdu : *PeekPointer (psdu)) + { + // Dequeue the MPDU if it is stored in a queue + DequeueMpdu (mpdu); + NotifyPacketDiscarded (mpdu); + } m_dcf->ResetCw (); } else { - NS_LOG_DEBUG ("Missed CTS, retransmit RTS"); + NS_LOG_DEBUG ("Missed CTS, retransmit MPDU(s)"); m_dcf->UpdateFailedCw (); } - // Make the sequence number of the MPDU available again if the MPDU has never - // been transmitted, both in case the MPDU has been discarded and in case the - // MPDU has to be transmitted (because a new sequence number is assigned to + // Make the sequence numbers of the MPDUs available again if the MPDUs have never + // been transmitted, both in case the MPDUs have been discarded and in case the + // MPDUs have to be transmitted (because a new sequence number is assigned to // MPDUs that have never been transmitted and are selected for transmission) - ReleaseSequenceNumber (m_mpdu); - m_mpdu = 0; + for (const auto& mpdu : *PeekPointer (psdu)) + { + ReleaseSequenceNumber (mpdu); + } TransmissionFailed (); } diff --git a/src/wifi/model/frame-exchange-manager.h b/src/wifi/model/frame-exchange-manager.h index 1c9b5003d..46079bf11 100644 --- a/src/wifi/model/frame-exchange-manager.h +++ b/src/wifi/model/frame-exchange-manager.h @@ -531,6 +531,13 @@ protected: * \param txVector the TXVECTOR used to transmit the RTS frame */ virtual void CtsTimeout (Ptr rts, const WifiTxVector& txVector); + /** + * Take required actions when the CTS timer fired after sending an RTS to + * protect the given PSDU expires. + * + * \param psdu the PSDU protected by the failed RTS + */ + void DoCtsTimeout (Ptr psdu); private: /** diff --git a/src/wifi/model/he/he-frame-exchange-manager.cc b/src/wifi/model/he/he-frame-exchange-manager.cc index 2fe664771..3b2c9ffaf 100644 --- a/src/wifi/model/he/he-frame-exchange-manager.cc +++ b/src/wifi/model/he/he-frame-exchange-manager.cc @@ -227,7 +227,12 @@ HeFrameExchangeManager::SendPsduMapWithProtection (WifiPsduMap psduMap, WifiTxPa WifiAckManager::SetQosAckPolicy (psdu.second, m_txParams.m_acknowledgment.get ()); } - if (m_txParams.m_protection->method == WifiProtection::NONE) + if (m_txParams.m_protection->method == WifiProtection::RTS_CTS) + { + NS_ABORT_MSG_IF (m_psduMap.size () > 1, "Cannot use RTS/CTS with MU PPDUs"); + SendRts (m_txParams); + } + else if (m_txParams.m_protection->method == WifiProtection::NONE) { SendPsduMap (); } @@ -250,6 +255,24 @@ HeFrameExchangeManager::GetPsduTo (Mac48Address to, const WifiPsduMap& psduMap) return nullptr; } +void +HeFrameExchangeManager::CtsTimeout (Ptr rts, const WifiTxVector& txVector) +{ + NS_LOG_FUNCTION (this << *rts << txVector); + + if (m_psduMap.empty ()) + { + // A CTS Timeout occurred when protecting a single PSDU that is not included + // in a DL MU PPDU is handled by the parent classes + VhtFrameExchangeManager::CtsTimeout (rts, txVector); + return; + } + + NS_ABORT_MSG_IF (m_psduMap.size () > 1, "RTS/CTS cannot be used to protect an MU PPDU"); + DoCtsTimeout (m_psduMap.begin ()->second); + m_psduMap.clear (); +} + void HeFrameExchangeManager::SendPsduMap (void) { @@ -1455,7 +1478,26 @@ HeFrameExchangeManager::ReceiveMpdu (Ptr mpdu, RxSignalInfo rx if (hdr.IsCtl ()) { - if (hdr.IsAck () && m_txTimer.IsRunning () + if (hdr.IsCts () && m_txTimer.IsRunning () && m_txTimer.GetReason () == WifiTxTimer::WAIT_CTS + && m_psduMap.size () == 1) + { + NS_ABORT_MSG_IF (inAmpdu, "Received CTS as part of an A-MPDU"); + NS_ASSERT (hdr.GetAddr1 () == m_self); + + Mac48Address sender = m_psduMap.begin ()->second->GetAddr1 (); + NS_LOG_DEBUG ("Received CTS from=" << sender); + + SnrTag tag; + mpdu->GetPacket ()->PeekPacketTag (tag); + m_mac->GetWifiRemoteStationManager ()->ReportRxOk (sender, rxSignalInfo, txVector); + m_mac->GetWifiRemoteStationManager ()->ReportRtsOk (m_psduMap.begin ()->second->GetHeader (0), + rxSignalInfo.snr, txVector.GetMode (), tag.Get ()); + + m_txTimer.Cancel (); + m_channelAccessManager->NotifyCtsTimeoutResetNow (); + Simulator::Schedule (m_phy->GetSifs (), &HeFrameExchangeManager::SendPsduMap, this); + } + else if (hdr.IsAck () && m_txTimer.IsRunning () && m_txTimer.GetReason () == WifiTxTimer::WAIT_NORMAL_ACK_AFTER_DL_MU_PPDU) { NS_ASSERT (hdr.GetAddr1 () == m_self); diff --git a/src/wifi/model/he/he-frame-exchange-manager.h b/src/wifi/model/he/he-frame-exchange-manager.h index 24b57e293..c4695dfb8 100644 --- a/src/wifi/model/he/he-frame-exchange-manager.h +++ b/src/wifi/model/he/he-frame-exchange-manager.h @@ -101,6 +101,7 @@ protected: Time GetTxDuration (uint32_t ppduPayloadSize, Mac48Address receiver, const WifiTxParameters& txParams) const override; bool SendMpduFromBaManager (Ptr edca, Time availableTime, bool initialFrame) override; + void CtsTimeout (Ptr rts, const WifiTxVector& txVector) override; /** * Send a map of PSDUs as a DL MU PPDU. diff --git a/src/wifi/model/ht/ht-frame-exchange-manager.cc b/src/wifi/model/ht/ht-frame-exchange-manager.cc index d6aa73f6d..9c961200b 100644 --- a/src/wifi/model/ht/ht-frame-exchange-manager.cc +++ b/src/wifi/model/ht/ht-frame-exchange-manager.cc @@ -768,36 +768,8 @@ HtFrameExchangeManager::CtsTimeout (Ptr rts, const WifiTxVecto return; } - NS_ASSERT (m_psdu->GetNMpdus () > 1); - m_mac->GetWifiRemoteStationManager ()->ReportRtsFailed (m_psdu->GetHeader (0)); - - if (!m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (*m_psdu->begin ())) - { - NS_LOG_DEBUG ("Missed CTS, discard MPDUs"); - m_mac->GetWifiRemoteStationManager ()->ReportFinalRtsFailed (m_psdu->GetHeader (0)); - // Dequeue the MPDUs if they are stored in a queue - DequeuePsdu (m_psdu); - for (const auto& mpdu : *PeekPointer (m_psdu)) - { - NotifyPacketDiscarded (mpdu); - } - m_edca->ResetCw (); - } - else - { - NS_LOG_DEBUG ("Missed CTS, retransmit MPDUs"); - m_edca->UpdateFailedCw (); - } - // Make the sequence numbers of the MPDUs available again if the MPDUs have never - // been transmitted, both in case the MPDUs have been discarded and in case the - // MPDUs have to be transmitted (because a new sequence number is assigned to - // MPDUs that have never been transmitted and are selected for transmission) - for (const auto& mpdu : *PeekPointer (m_psdu)) - { - ReleaseSequenceNumber (mpdu); - } - m_psdu = 0; - TransmissionFailed (); + DoCtsTimeout (m_psdu); + m_psdu = nullptr; } void