diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f6b9af91c..c21c11f6f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -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 diff --git a/src/wifi/model/channel-access-manager.cc b/src/wifi/model/channel-access-manager.cc index 47ccb909a..272f296c9 100644 --- a/src/wifi/model/channel-access-manager.cc +++ b/src/wifi/model/channel-access-manager.cc @@ -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 diff --git a/src/wifi/model/channel-access-manager.h b/src/wifi/model/channel-access-manager.h index 6c0847929..ee8a39d57 100644 --- a/src/wifi/model/channel-access-manager.h +++ b/src/wifi/model/channel-access-manager.h @@ -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 * diff --git a/src/wifi/model/eht/advanced-emlsr-manager.cc b/src/wifi/model/eht/advanced-emlsr-manager.cc index e33986a1b..8c88e246f 100644 --- a/src/wifi/model/eht/advanced-emlsr-manager.cc +++ b/src/wifi/model/eht/advanced-emlsr-manager.cc @@ -63,7 +63,7 @@ class EmlsrPhyListener : public WifiPhyListener m_emlsrManager); } - void NotifyRxEndError() override + void NotifyRxEndError(const WifiTxVector& /* txVector */) override { } diff --git a/src/wifi/model/he/he-phy.cc b/src/wifi/model/he/he-phy.cc index 51bf1c1e3..9050953b3 100644 --- a/src/wifi/model/he/he-phy.cc +++ b/src/wifi/model/he/he-phy.cc @@ -873,7 +873,7 @@ HePhy::RxPayloadFailed(Ptr 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 ppdu) } else { - m_state->SwitchFromRxEndError(); + m_state->SwitchFromRxEndError(ppdu->GetTxVector()); } NotifyInterferenceRxEndAndClear(true); // reset WifiPhy m_rxHeTbPpdus = 0; diff --git a/src/wifi/model/phy-entity.cc b/src/wifi/model/phy-entity.cc index 6e22407b6..715a6f8bc 100644 --- a/src/wifi/model/phy-entity.cc +++ b/src/wifi/model/phy-entity.cc @@ -785,7 +785,7 @@ void PhyEntity::RxPayloadFailed(Ptr psdu, double snr, const WifiTxVector& txVector) { NS_LOG_FUNCTION(this << *psdu << txVector << snr); - m_state->SwitchFromRxEndError(); + m_state->SwitchFromRxEndError(txVector); } void diff --git a/src/wifi/model/wifi-phy-listener.h b/src/wifi/model/wifi-phy-listener.h index 1e1117904..26c307656 100644 --- a/src/wifi/model/wifi-phy-listener.h +++ b/src/wifi/model/wifi-phy-listener.h @@ -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 diff --git a/src/wifi/model/wifi-phy-state-helper.cc b/src/wifi/model/wifi-phy-state-helper.cc index 86038a329..7fdec91d6 100644 --- a/src/wifi/model/wifi-phy-state-helper.cc +++ b/src/wifi/model/wifi-phy-state-helper.cc @@ -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(); } diff --git a/src/wifi/model/wifi-phy-state-helper.h b/src/wifi/model/wifi-phy-state-helper.h index 2e05c2fde..c9a22fb1d 100644 --- a/src/wifi/model/wifi-phy-state-helper.h +++ b/src/wifi/model/wifi-phy-state-helper.h @@ -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 diff --git a/src/wifi/model/wifi-radio-energy-model.cc b/src/wifi/model/wifi-radio-energy-model.cc index 617f35de5..b1bb89c8b 100644 --- a/src/wifi/model/wifi-radio-energy-model.cc +++ b/src/wifi/model/wifi-radio-energy-model.cc @@ -514,7 +514,7 @@ WifiRadioEnergyModelPhyListener::NotifyRxEndOk() } void -WifiRadioEnergyModelPhyListener::NotifyRxEndError() +WifiRadioEnergyModelPhyListener::NotifyRxEndError(const WifiTxVector& /* txVector */) { NS_LOG_FUNCTION(this); if (m_changeStateCallback.IsNull()) diff --git a/src/wifi/model/wifi-radio-energy-model.h b/src/wifi/model/wifi-radio-energy-model.h index 3705b199f..a1e4b83e6 100644 --- a/src/wifi/model/wifi-radio-energy-model.h +++ b/src/wifi/model/wifi-radio-energy-model.h @@ -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, diff --git a/src/wifi/model/wifi-utils.cc b/src/wifi/model/wifi-utils.cc index baf5fee58..9fc1a2335 100644 --- a/src/wifi/model/wifi-utils.cc +++ b/src/wifi/model/wifi-utils.cc @@ -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) { diff --git a/src/wifi/model/wifi-utils.h b/src/wifi/model/wifi-utils.h index 9a381106a..88180e1d3 100644 --- a/src/wifi/model/wifi-utils.h +++ b/src/wifi/model/wifi-utils.h @@ -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 diff --git a/src/wifi/test/channel-access-manager-test.cc b/src/wifi/test/channel-access-manager-test.cc index 71b33be0f..0d847b9ae 100644 --- a/src/wifi/test/channel-access-manager-test.cc +++ b/src/wifi/test/channel-access-manager-test.cc @@ -732,7 +732,21 @@ ChannelAccessManagerTest::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 @@ -747,7 +761,21 @@ ChannelAccessManagerTest::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, diff --git a/src/wifi/test/spectrum-wifi-phy-test.cc b/src/wifi/test/spectrum-wifi-phy-test.cc index af88943ef..fdb031e73 100644 --- a/src/wifi/test/spectrum-wifi-phy-test.cc +++ b/src/wifi/test/spectrum-wifi-phy-test.cc @@ -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; } diff --git a/src/wifi/test/wifi-phy-cca-test.cc b/src/wifi/test/wifi-phy-cca-test.cc index 428ff97c0..5ee9c7129 100644 --- a/src/wifi/test/wifi-phy-cca-test.cc +++ b/src/wifi/test/wifi-phy-cca-test.cc @@ -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 diff --git a/src/wifi/test/wifi-phy-ofdma-test.cc b/src/wifi/test/wifi-phy-ofdma-test.cc index 6deb21442..a6f7bfa6a 100644 --- a/src/wifi/test/wifi-phy-ofdma-test.cc +++ b/src/wifi/test/wifi-phy-ofdma-test.cc @@ -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;