wifi: Enable protection for DL MU PPDUs including one PSDU

This commit is contained in:
Stefano Avallone
2022-04-14 09:35:37 +02:00
committed by Tom Henderson
parent 72c64cd500
commit 0816eebc29
5 changed files with 81 additions and 45 deletions

View File

@@ -810,28 +810,42 @@ FrameExchangeManager::CtsTimeout (Ptr<WifiMacQueueItem> rts, const WifiTxVector&
{
NS_LOG_FUNCTION (this << *rts << txVector);
m_mac->GetWifiRemoteStationManager ()->ReportRtsFailed (m_mpdu->GetHeader ());
DoCtsTimeout (Create<WifiPsdu> (m_mpdu, true));
m_mpdu = nullptr;
}
if (!m_mac->GetWifiRemoteStationManager ()->NeedRetransmission (m_mpdu))
void
FrameExchangeManager::DoCtsTimeout (Ptr<WifiPsdu> 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 ();
}

View File

@@ -531,6 +531,13 @@ protected:
* \param txVector the TXVECTOR used to transmit the RTS frame
*/
virtual void CtsTimeout (Ptr<WifiMacQueueItem> 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<WifiPsdu> psdu);
private:
/**

View File

@@ -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<WifiMacQueueItem> 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<WifiMacQueueItem> 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);

View File

@@ -101,6 +101,7 @@ protected:
Time GetTxDuration (uint32_t ppduPayloadSize, Mac48Address receiver,
const WifiTxParameters& txParams) const override;
bool SendMpduFromBaManager (Ptr<QosTxop> edca, Time availableTime, bool initialFrame) override;
void CtsTimeout (Ptr<WifiMacQueueItem> rts, const WifiTxVector& txVector) override;
/**
* Send a map of PSDUs as a DL MU PPDU.

View File

@@ -768,36 +768,8 @@ HtFrameExchangeManager::CtsTimeout (Ptr<WifiMacQueueItem> 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