wifi: Fix EIFS computation

EIFS depends on the modulation class of the PPDU whose reception failed
rather than on the latest standard supported by a device
This commit is contained in:
Stefano Avallone
2025-03-05 12:45:49 +01:00
parent 28828fe462
commit 2a90d4dddc
17 changed files with 125 additions and 23 deletions

View File

@@ -42,6 +42,7 @@ The required Doxygen version for documentation generation is now version 1.13.
- (wifi) #2368 - Fix various issues related to Content Channels and RU allocation. Fixes mostly covers cases where OFDMA is used with central 26 tones, where a single user is being assigned the whole PPDU bandwidth or where a RU is larger than 20 MHz.
- (zigbee) !2383 - Fix malformed RREP command with missing command options field.
- (wifi) Fix the time the `NSlotsLeftAlert` trace source of `ChannelAccessManager` is fired (it cannot be earlier than the access grant start time)
- (wifi) Fix the EIFS computation, which depends on the modulation class of the PPDU whose reception failed rather than on the latest standard supported by a device
## Release 3.44

View File

@@ -90,11 +90,11 @@ class PhyListener : public ns3::WifiPhyListener
}
}
void NotifyRxEndError() override
void NotifyRxEndError(const WifiTxVector& txVector) override
{
if (m_active)
{
m_cam->NotifyRxEndErrorNow();
m_cam->NotifyRxEndErrorNow(txVector);
}
}
@@ -985,14 +985,14 @@ ChannelAccessManager::NotifyRxEndOkNow()
}
void
ChannelAccessManager::NotifyRxEndErrorNow()
ChannelAccessManager::NotifyRxEndErrorNow(const WifiTxVector& txVector)
{
NS_LOG_FUNCTION(this);
NS_LOG_DEBUG("rx end error");
// we expect the PHY to notify us of the start of a CCA busy period, if needed
m_lastRx.end = Simulator::Now();
m_lastRxReceivedOk = false;
m_eifsNoDifs = m_phy->GetSifs() + m_phy->GetAckTxTime();
m_eifsNoDifs = m_phy->GetSifs() + GetEstimatedAckTxTime(txVector);
}
void

View File

@@ -33,6 +33,7 @@ class WifiPhy;
class PhyListener;
class Txop;
class FrameExchangeManager;
class WifiTxVector;
enum AcIndex : uint8_t; // opaque enum declaration
/**
@@ -236,8 +237,10 @@ class ChannelAccessManager : public Object
/**
* Notify the Txop that a packet reception was just
* completed unsuccessfuly.
*
* @param txVector the TXVECTOR used for transmission
*/
void NotifyRxEndErrorNow();
void NotifyRxEndErrorNow(const WifiTxVector& txVector);
/**
* @param duration expected duration of transmission
*

View File

@@ -63,7 +63,7 @@ class EmlsrPhyListener : public WifiPhyListener
m_emlsrManager);
}
void NotifyRxEndError() override
void NotifyRxEndError(const WifiTxVector& /* txVector */) override
{
}

View File

@@ -873,7 +873,7 @@ HePhy::RxPayloadFailed(Ptr<const WifiPsdu> psdu, double snr, const WifiTxVector&
NS_LOG_FUNCTION(this << *psdu << txVector << snr);
if (!txVector.IsUlMu())
{
m_state->SwitchFromRxEndError();
m_state->SwitchFromRxEndError(txVector);
}
}
@@ -906,7 +906,7 @@ HePhy::DoEndReceivePayload(Ptr<const WifiPpdu> ppdu)
}
else
{
m_state->SwitchFromRxEndError();
m_state->SwitchFromRxEndError(ppdu->GetTxVector());
}
NotifyInterferenceRxEndAndClear(true); // reset WifiPhy
m_rxHeTbPpdus = 0;

View File

@@ -785,7 +785,7 @@ void
PhyEntity::RxPayloadFailed(Ptr<const WifiPsdu> psdu, double snr, const WifiTxVector& txVector)
{
NS_LOG_FUNCTION(this << *psdu << txVector << snr);
m_state->SwitchFromRxEndError();
m_state->SwitchFromRxEndError(txVector);
}
void

View File

@@ -17,6 +17,8 @@
namespace ns3
{
class WifiTxVector;
/**
* @brief receive notifications about PHY events.
*/
@@ -51,11 +53,13 @@ class WifiPhyListener
*/
virtual void NotifyRxEndOk() = 0;
/**
* @param txVector the TXVECTOR used for transmission
*
* We have received the last bit of a packet for which
* NotifyRxStart was invoked first and, the packet has
* _not_ been successfully received.
*/
virtual void NotifyRxEndError() = 0;
virtual void NotifyRxEndError(const WifiTxVector& txVector) = 0;
/**
* @param duration the expected transmission duration.
* @param txPower the nominal TX power

View File

@@ -482,11 +482,11 @@ WifiPhyStateHelper::SwitchFromRxEndOk()
}
void
WifiPhyStateHelper::SwitchFromRxEndError()
WifiPhyStateHelper::SwitchFromRxEndError(const WifiTxVector& txVector)
{
NS_LOG_FUNCTION(this);
NS_ASSERT(m_endRx == Simulator::Now());
NotifyListeners(&WifiPhyListener::NotifyRxEndError);
NotifyListeners(&WifiPhyListener::NotifyRxEndError, txVector);
DoSwitchFromRx();
}

View File

@@ -246,8 +246,10 @@ class WifiPhyStateHelper : public Object
void SwitchFromRxEndOk();
/**
* Switch from RX after the reception failed.
*
* @param txVector the TXVECTOR used for transmission of failed frame
*/
void SwitchFromRxEndError();
void SwitchFromRxEndError(const WifiTxVector& txVector);
/**
* Abort current reception following a CCA reset request.
* @param operatingWidth the channel width the PHY is operating on

View File

@@ -514,7 +514,7 @@ WifiRadioEnergyModelPhyListener::NotifyRxEndOk()
}
void
WifiRadioEnergyModelPhyListener::NotifyRxEndError()
WifiRadioEnergyModelPhyListener::NotifyRxEndError(const WifiTxVector& /* txVector */)
{
NS_LOG_FUNCTION(this);
if (m_changeStateCallback.IsNull())

View File

@@ -56,7 +56,7 @@ class WifiRadioEnergyModelPhyListener : public WifiPhyListener
void NotifyRxStart(Time duration) override;
void NotifyRxEndOk() override;
void NotifyRxEndError() override;
void NotifyRxEndError(const WifiTxVector& txVector) override;
void NotifyTxStart(Time duration, dBm_u txPower) override;
void NotifyCcaBusyStart(Time duration,
WifiChannelListType channelType,

View File

@@ -13,6 +13,7 @@
#include "gcr-manager.h"
#include "wifi-mac-header.h"
#include "wifi-mac-trailer.h"
#include "wifi-tx-vector.h"
#include "ns3/packet.h"
@@ -109,6 +110,61 @@ GetCtsSize()
return size;
}
Time
GetEstimatedAckTxTime(const WifiTxVector& txVector)
{
auto modClass = txVector.GetModulationClass();
switch (modClass)
{
case WIFI_MOD_CLASS_DSSS:
case WIFI_MOD_CLASS_HR_DSSS:
if (txVector.GetMode().GetDataRate(txVector) == 1e6)
{
return MicroSeconds(304);
}
else if (txVector.GetPreambleType() == WIFI_PREAMBLE_LONG)
{
return MicroSeconds(248);
}
else
{
return MicroSeconds(152);
}
break;
case WIFI_MOD_CLASS_ERP_OFDM:
case WIFI_MOD_CLASS_OFDM:
if (auto constSize = txVector.GetMode().GetConstellationSize(); constSize == 2)
{
return MicroSeconds(44);
}
else if (constSize == 4)
{
return MicroSeconds(32);
}
else
{
return MicroSeconds(28);
}
break;
default: {
auto staId = (txVector.IsMu() ? txVector.GetHeMuUserInfoMap().begin()->first : SU_STA_ID);
if (const auto constSize = txVector.GetMode(staId).GetConstellationSize(); constSize == 2)
{
return MicroSeconds(68);
}
else if (constSize == 4)
{
return MicroSeconds(44);
}
else
{
return MicroSeconds(32);
}
}
}
}
bool
IsInWindow(uint16_t seq, uint16_t winstart, uint16_t winsize)
{

View File

@@ -27,6 +27,7 @@ class Mac48Address;
class WifiMacHeader;
class Packet;
class WifiMac;
class WifiTxVector;
/**
* Wifi direction. Values are those defined for the TID-to-Link Mapping Control Direction
@@ -195,6 +196,13 @@ uint32_t GetRtsSize();
* @return the total CTS size in bytes
*/
uint32_t GetCtsSize();
/**
* @param txVector the TXVECTOR used to transmit a frame whose reception failed
* @return the estimated Ack TX time, based on Table 10-8 of IEEE 802.11REVme D7.0
*/
Time GetEstimatedAckTxTime(const WifiTxVector& txVector);
/**
* @param seq MPDU sequence number
* @param winstart sequence number window start

View File

@@ -732,7 +732,21 @@ ChannelAccessManagerTest<TxopType>::AddRxErrorEvt(uint64_t at, uint64_t duration
MicroSeconds(duration));
Simulator::Schedule(MicroSeconds(at + duration) - Now(),
&ChannelAccessManager::NotifyRxEndErrorNow,
m_ChannelAccessManager);
m_ChannelAccessManager,
WifiTxVector(OfdmPhy::GetOfdmRate6Mbps(),
1,
WIFI_PREAMBLE_LONG,
NanoSeconds(800),
1,
1,
0,
MHz_u{20},
false,
false,
false,
0,
0,
false));
}
template <typename TxopType>
@@ -747,7 +761,21 @@ ChannelAccessManagerTest<TxopType>::AddRxErrorEvt(uint64_t at,
MicroSeconds(duration));
Simulator::Schedule(MicroSeconds(at + timeUntilError) - Now(),
&ChannelAccessManager::NotifyRxEndErrorNow,
m_ChannelAccessManager);
m_ChannelAccessManager,
WifiTxVector(OfdmPhy::GetOfdmRate6Mbps(),
1,
WIFI_PREAMBLE_LONG,
NanoSeconds(800),
1,
1,
0,
MHz_u{20},
false,
false,
false,
0,
0,
false));
Simulator::Schedule(MicroSeconds(at + timeUntilError) - Now(),
&ChannelAccessManager::NotifyCcaBusyStartNow,
m_ChannelAccessManager,

View File

@@ -327,9 +327,9 @@ class TestPhyListener : public ns3::WifiPhyListener
++m_notifyRxEndOk;
}
void NotifyRxEndError() override
void NotifyRxEndError(const WifiTxVector& txVector) override
{
NS_LOG_FUNCTION(this);
NS_LOG_FUNCTION(this << txVector);
++m_notifyRxEndError;
}

View File

@@ -627,9 +627,9 @@ class CcaTestPhyListener : public ns3::WifiPhyListener
NS_LOG_FUNCTION(this);
}
void NotifyRxEndError() override
void NotifyRxEndError(const WifiTxVector& txVector) override
{
NS_LOG_FUNCTION(this);
NS_LOG_FUNCTION(this << txVector);
}
void NotifyTxStart(Time duration, dBm_u txPower) override

View File

@@ -2890,9 +2890,9 @@ class OfdmaTestPhyListener : public ns3::WifiPhyListener
m_lastRxSuccess = true;
}
void NotifyRxEndError() override
void NotifyRxEndError(const WifiTxVector& txVector) override
{
NS_LOG_FUNCTION(this);
NS_LOG_FUNCTION(this << txVector);
m_lastRxEnd = Simulator::Now();
++m_notifyRxEnd;
m_lastRxSuccess = false;