wifi: Decouple protection and TX plus acknowledgment

...to make it possible, e.g., to use MU-RTS to protect a SU transmission
This commit is contained in:
Stefano Avallone
2023-02-28 20:01:35 +01:00
parent 0d67c14b85
commit abddcf82a7
6 changed files with 102 additions and 46 deletions

View File

@@ -414,20 +414,7 @@ FrameExchangeManager::SendMpduWithProtection(Ptr<WifiMpdu> mpdu, WifiTxParameter
m_mpdu->SetInFlight(m_linkId);
}
switch (m_txParams.m_protection->method)
{
case WifiProtection::RTS_CTS:
SendRts(m_txParams);
break;
case WifiProtection::CTS_TO_SELF:
SendCtsToSelf(m_txParams);
break;
case WifiProtection::NONE:
SendMpdu();
break;
default:
NS_ABORT_MSG("Unknown protection type");
}
StartProtection(m_txParams);
if (m_txParams.m_acknowledgment->method == WifiAcknowledgment::NONE)
{
@@ -436,6 +423,35 @@ FrameExchangeManager::SendMpduWithProtection(Ptr<WifiMpdu> mpdu, WifiTxParameter
}
}
void
FrameExchangeManager::StartProtection(const WifiTxParameters& txParams)
{
NS_LOG_FUNCTION(this << &txParams);
switch (txParams.m_protection->method)
{
case WifiProtection::RTS_CTS:
SendRts(txParams);
break;
case WifiProtection::CTS_TO_SELF:
SendCtsToSelf(txParams);
break;
case WifiProtection::NONE:
ProtectionCompleted();
break;
default:
NS_ABORT_MSG("Unknown protection type: " << txParams.m_protection.get());
}
}
void
FrameExchangeManager::ProtectionCompleted()
{
NS_LOG_FUNCTION(this);
NS_ASSERT(m_mpdu);
SendMpdu();
}
void
FrameExchangeManager::SendMpdu()
{
@@ -794,7 +810,9 @@ FrameExchangeManager::SendCtsToSelf(const WifiTxParameters& txParams)
Time ctsDuration = m_phy->CalculateTxDuration(GetCtsSize(),
ctsToSelfProtection->ctsTxVector,
m_phy->GetPhyBand());
Simulator::Schedule(ctsDuration + m_phy->GetSifs(), &FrameExchangeManager::SendMpdu, this);
Simulator::Schedule(ctsDuration + m_phy->GetSifs(),
&FrameExchangeManager::ProtectionCompleted,
this);
}
void
@@ -1269,7 +1287,7 @@ FrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
m_txTimer.Cancel();
m_channelAccessManager->NotifyCtsTimeoutResetNow();
Simulator::Schedule(m_phy->GetSifs(), &FrameExchangeManager::SendMpdu, this);
Simulator::Schedule(m_phy->GetSifs(), &FrameExchangeManager::ProtectionCompleted, this);
}
else if (hdr.IsAck() && m_mpdu && m_txTimer.IsRunning() &&
m_txTimer.GetReason() == WifiTxTimer::WAIT_NORMAL_ACK)

View File

@@ -299,6 +299,18 @@ class FrameExchangeManager : public Object
*/
void SendMpduWithProtection(Ptr<WifiMpdu> mpdu, WifiTxParameters& txParams);
/**
* Start the protection mechanism indicated by the given TX parameters
*
* \param txParams the TX parameters
*/
virtual void StartProtection(const WifiTxParameters& txParams);
/**
* Transmit prepared frame upon successful protection mechanism.
*/
virtual void ProtectionCompleted();
/**
* Update the NAV, if needed, based on the Duration/ID of the given <i>psdu</i>.
*

View File

@@ -282,25 +282,39 @@ HeFrameExchangeManager::SendPsduMapWithProtection(WifiPsduMap psduMap, WifiTxPar
}
}
if (m_txParams.m_protection->method == WifiProtection::RTS_CTS)
StartProtection(m_txParams);
}
void
HeFrameExchangeManager::StartProtection(const WifiTxParameters& txParams)
{
NS_LOG_FUNCTION(this << &txParams);
NS_ABORT_MSG_IF(m_psduMap.size() > 1 &&
txParams.m_protection->method == WifiProtection::RTS_CTS,
"Cannot use RTS/CTS with MU PPDUs");
if (txParams.m_protection->method == WifiProtection::MU_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::MU_RTS_CTS)
{
SendMuRts(m_txParams);
}
else if (m_txParams.m_protection->method == WifiProtection::NONE)
{
SendPsduMap();
SendMuRts(txParams);
}
else
{
NS_ABORT_MSG("Unknown or prohibited protection type: " << m_txParams.m_protection.get());
VhtFrameExchangeManager::StartProtection(txParams);
}
}
void
HeFrameExchangeManager::ProtectionCompleted()
{
NS_LOG_FUNCTION(this);
if (!m_psduMap.empty())
{
SendPsduMap();
return;
}
VhtFrameExchangeManager::ProtectionCompleted();
}
Time
HeFrameExchangeManager::GetMuRtsDurationId(uint32_t muRtsSize,
const WifiTxVector& muRtsTxVector,
@@ -387,7 +401,13 @@ HeFrameExchangeManager::CtsAfterMuRtsTimeout(Ptr<WifiMpdu> muRts, const WifiTxVe
{
NS_LOG_FUNCTION(this << *muRts << txVector);
NS_ASSERT(!m_psduMap.empty());
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(muRts, txVector);
return;
}
for (const auto& psdu : m_psduMap)
{
@@ -2295,9 +2315,11 @@ HeFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
m_txTimer.Cancel();
m_channelAccessManager->NotifyCtsTimeoutResetNow();
Simulator::Schedule(m_phy->GetSifs(), &HeFrameExchangeManager::SendPsduMap, this);
Simulator::Schedule(m_phy->GetSifs(),
&HeFrameExchangeManager::ProtectionCompleted,
this);
}
else if (hdr.IsCts() && !m_psduMap.empty() && m_txTimer.IsRunning() &&
else if (hdr.IsCts() && m_txTimer.IsRunning() &&
m_txTimer.GetReason() == WifiTxTimer::WAIT_CTS_AFTER_MU_RTS)
{
NS_ABORT_MSG_IF(inAmpdu, "Received CTS as part of an A-MPDU");
@@ -2307,7 +2329,9 @@ HeFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
m_txTimer.Cancel();
m_channelAccessManager->NotifyCtsTimeoutResetNow();
Simulator::Schedule(m_phy->GetSifs(), &HeFrameExchangeManager::SendPsduMap, this);
Simulator::Schedule(m_phy->GetSifs(),
&HeFrameExchangeManager::ProtectionCompleted,
this);
}
else if (hdr.IsAck() && m_txTimer.IsRunning() &&
m_txTimer.GetReason() == WifiTxTimer::WAIT_NORMAL_ACK_AFTER_DL_MU_PPDU)

View File

@@ -156,6 +156,8 @@ class HeFrameExchangeManager : public VhtFrameExchangeManager
void CtsTimeout(Ptr<WifiMpdu> rts, const WifiTxVector& txVector) override;
void UpdateNav(Ptr<const WifiPsdu> psdu, const WifiTxVector& txVector) override;
void NavResetTimeout() override;
void StartProtection(const WifiTxParameters& txParams) override;
void ProtectionCompleted() override;
/**
* Clear the TXOP holder if the intra-BSS NAV counted down to zero (includes the case

View File

@@ -954,22 +954,19 @@ HtFrameExchangeManager::SendPsduWithProtection(Ptr<WifiPsdu> psdu, WifiTxParamet
}
}
if (m_txParams.m_protection->method == WifiProtection::RTS_CTS)
{
SendRts(m_txParams);
}
else if (m_txParams.m_protection->method == WifiProtection::CTS_TO_SELF)
{
SendCtsToSelf(m_txParams);
}
else if (m_txParams.m_protection->method == WifiProtection::NONE)
StartProtection(m_txParams);
}
void
HtFrameExchangeManager::ProtectionCompleted()
{
NS_LOG_FUNCTION(this);
if (m_psdu)
{
SendPsdu();
return;
}
else
{
NS_ABORT_MSG("Unknown protection type");
}
QosFrameExchangeManager::ProtectionCompleted();
}
void
@@ -1552,7 +1549,9 @@ HtFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
m_txTimer.Cancel();
m_channelAccessManager->NotifyCtsTimeoutResetNow();
Simulator::Schedule(m_phy->GetSifs(), &HtFrameExchangeManager::SendPsdu, this);
Simulator::Schedule(m_phy->GetSifs(),
&HtFrameExchangeManager::ProtectionCompleted,
this);
}
else if (hdr.IsBlockAck() && m_txTimer.IsRunning() &&
m_txTimer.GetReason() == WifiTxTimer::WAIT_BLOCK_ACK && hdr.GetAddr1() == m_self)

View File

@@ -200,6 +200,7 @@ class HtFrameExchangeManager : public QosFrameExchangeManager
void FinalizeMacHeader(Ptr<const WifiPsdu> psdu) override;
void CtsTimeout(Ptr<WifiMpdu> rts, const WifiTxVector& txVector) override;
void TransmissionSucceeded() override;
void ProtectionCompleted() override;
/**
* Get a PSDU containing the given MPDU