From 34956c3ceb672afb6cd28f883f23bb21206a6dfd Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Mon, 8 Jan 2024 22:59:09 +0100 Subject: [PATCH] wifi: Add a trace source to WifiPhy to notify of MAC header reception --- CHANGES.md | 1 + src/wifi/model/phy-entity.cc | 44 ++++++++++++++++++++++++++++++++++++ src/wifi/model/phy-entity.h | 3 ++- src/wifi/model/wifi-phy.cc | 11 +++++++++ src/wifi/model/wifi-phy.h | 24 ++++++++++++++++++++ 5 files changed, 82 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 801364fda..00742cb47 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,7 @@ Changes from ns-3.42 to ns-3-dev * (tcp) A new trace source `TcpSocketBase::LastRtt` has been added for tracing the last RTT sample observed. The existing trace source `TcpSocketBase::Rtt` is still providing the smoothed RTT, although it had been incorrectly documented as providing the last RTT. * (core) Added `LaplacianRandomVariable` class implementing the Laplacian random variable, and `LargestExtremeValueRandomVariable` class implementing the Largest Extreme Value random variable. +* (wifi) Added a new trace source to `WifiPhy`: **PhyRxMacHeaderEnd**, which is fired when the reception of the MAC header of an MPDU is completed and provides the MAC header and the remaining PSDU duration. The trace source is actually fired when the new **NotifyMacHdrRxEnd** attribute of `WifiPhy` is set to true (it is set to false by default). ### Changes to existing API diff --git a/src/wifi/model/phy-entity.cc b/src/wifi/model/phy-entity.cc index f81002ecc..35e4252fa 100644 --- a/src/wifi/model/phy-entity.cc +++ b/src/wifi/model/phy-entity.cc @@ -31,6 +31,7 @@ #include "wifi-utils.h" #include "ns3/assert.h" +#include "ns3/data-rate.h" #include "ns3/log.h" #include "ns3/packet.h" #include "ns3/simulator.h" @@ -611,6 +612,34 @@ PhyEntity::ScheduleEndOfMpdus(Ptr event) auto mpdu = psdu->begin(); for (size_t i = 0; i < nMpdus && mpdu != psdu->end(); ++mpdu) { + if (m_wifiPhy->m_notifyRxMacHeaderEnd) + { + // calculate MAC header size (including A-MPDU subframe header, if present) + auto macHdrSize = + (*mpdu)->GetHeader().GetSerializedSize() + (mpduType == NORMAL_MPDU ? 0 : 4); + // calculate the (approximate) duration of the MAC header TX + auto macHdrDuration = DataRate(txVector.GetMode(staId).GetDataRate(txVector, staId)) + .CalculateBytesTxTime(macHdrSize); + const auto widthBand = GetChannelWidthAndBand(txVector, staId); + const auto snrPer = m_wifiPhy->m_interference->CalculatePayloadSnrPer( + event, + widthBand.first, + widthBand.second, + staId, + {relativeStart, relativeStart + macHdrDuration}); + if (GetRandomValue() > snrPer.per) + { + // interference level should permit to correctly decode the MAC header + m_endOfMacHdrEvents.push_back( + Simulator::Schedule(endOfMpduDuration + macHdrDuration, [=, this]() { + m_wifiPhy->m_phyRxMacHeaderEndTrace((*mpdu)->GetHeader(), + txVector, + remainingAmpduDuration - + macHdrDuration); + })); + } + } + uint32_t size = (mpduType == NORMAL_MPDU) ? psdu->GetSize() : psdu->GetAmpduSubframeSize(i); Time mpduDuration = m_wifiPhy->GetPayloadDuration(size, txVector, @@ -925,6 +954,11 @@ PhyEntity::NotifyInterferenceRxEndAndClear(bool reset) NS_ASSERT(endOfMpduEvent.IsExpired()); } m_endOfMpduEvents.clear(); + for (const auto& endOfMacHdrEvent : m_endOfMacHdrEvents) + { + NS_ASSERT(endOfMacHdrEvent.IsExpired()); + } + m_endOfMacHdrEvents.clear(); if (reset) { m_wifiPhy->Reset(); @@ -1122,6 +1156,11 @@ PhyEntity::CancelAllEvents() endMpduEvent.Cancel(); } m_endOfMpduEvents.clear(); + for (auto& endMacHdrEvent : m_endOfMacHdrEvents) + { + endMacHdrEvent.Cancel(); + } + m_endOfMacHdrEvents.clear(); } bool @@ -1160,6 +1199,11 @@ PhyEntity::DoAbortCurrentReception(WifiPhyRxfailureReason reason) endMpduEvent.Cancel(); } m_endOfMpduEvents.clear(); + for (auto& endMacHdrEvent : m_endOfMacHdrEvents) + { + endMacHdrEvent.Cancel(); + } + m_endOfMacHdrEvents.clear(); } } diff --git a/src/wifi/model/phy-entity.h b/src/wifi/model/phy-entity.h index ea798d18a..2b2f6e9a8 100644 --- a/src/wifi/model/phy-entity.h +++ b/src/wifi/model/phy-entity.h @@ -954,7 +954,8 @@ class PhyEntity : public SimpleRefCount std::list m_modeList; //!< the list of supported modes std::vector m_endPreambleDetectionEvents; //!< the end of preamble detection events - std::vector m_endOfMpduEvents; //!< the end of MPDU events (only used for A-MPDUs) + std::vector m_endOfMpduEvents; //!< the end of MPDU events (only used for A-MPDUs) + std::vector m_endOfMacHdrEvents; //!< the end of MAC header events std::vector m_endRxPayloadEvents; //!< the end of receive events (only one unless UL MU reception) diff --git a/src/wifi/model/wifi-phy.cc b/src/wifi/model/wifi-phy.cc index e5af971bc..4cc2139a2 100644 --- a/src/wifi/model/wifi-phy.cc +++ b/src/wifi/model/wifi-phy.cc @@ -304,6 +304,12 @@ WifiPhy::GetTypeId() DoubleValue(100.0), // set to a high value so as to have no effect MakeDoubleAccessor(&WifiPhy::m_powerDensityLimit), MakeDoubleChecker()) + .AddAttribute("NotifyMacHdrRxEnd", + "Whether the PHY is capable of notifying the MAC about the end of " + "the reception of the MAC header of every MPDU.", + BooleanValue(false), + MakeBooleanAccessor(&WifiPhy::m_notifyRxMacHeaderEnd), + MakeBooleanChecker()) .AddTraceSource("PhyTxBegin", "Trace source indicating a packet " "has begun transmitting over the channel medium", @@ -335,6 +341,11 @@ WifiPhy::GetTypeId() "payload of a PPDU has begun", MakeTraceSourceAccessor(&WifiPhy::m_phyRxPayloadBeginTrace), "ns3::WifiPhy::PhyRxPayloadBeginTracedCallback") + .AddTraceSource("PhyRxMacHeaderEnd", + "Trace source indicating the MAC header of an MPDU has been " + "completely received.", + MakeTraceSourceAccessor(&WifiPhy::m_phyRxMacHeaderEndTrace), + "ns3::WifiPhy::PhyRxMacHeaderEndTracedCallback") .AddTraceSource("PhyRxEnd", "Trace source indicating a packet " "has been completely received from the channel medium " diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index 0f0ead255..3611ec3af 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -55,6 +55,7 @@ class WifiRadioEnergyModel; class UniformRandomVariable; class InterferenceHelper; class ErrorRateModel; +class WifiMacHeader; /** * \brief 802.11 PHY layer model @@ -766,6 +767,17 @@ class WifiPhy : public Object typedef void (*PhyRxPpduDropTracedCallback)(Ptr ppdu, WifiPhyRxfailureReason reason); + /** + * TracedCallback signature for end of MAC header reception events. + * + * \param macHdr the MAC header of the MPDU being received + * \param txVector the TXVECTOR used to transmit the PSDU + * \param psduDuration the remaining duration of the PSDU + */ + typedef void (*PhyRxMacHeaderEndTracedCallback)(const WifiMacHeader& macHdr, + const WifiTxVector& txVector, + Time psduDuration); + /** * Assign a fixed random variable stream number to the random variables * used by this model. Return the number of streams (possibly zero) that @@ -1505,6 +1517,17 @@ class WifiPhy : public Object */ TracedCallback m_phyRxPayloadBeginTrace; + /** + * The trace source fired when the reception of a MAC header ends. + * + * This traced callback models the behavior of real PHYs that are able to decode the MAC + * header of an MPDU being received and make the information therein available to the MAC + * as soon as the reception of the MAC header ends. + * + * \see class CallBackTraceSource + */ + TracedCallback m_phyRxMacHeaderEndTrace; + /** * The trace source fired when a packet ends the reception process from * the medium. @@ -1624,6 +1647,7 @@ class WifiPhy : public Object Ptr m_wifiRadioEnergyModel; //!< Wifi radio energy model Ptr m_postReceptionErrorModel; //!< Error model for receive packet events Time m_timeLastPreambleDetected; //!< Record the time the last preamble was detected + bool m_notifyRxMacHeaderEnd; //!< whether the PHY is capable of notifying MAC header RX end Callback m_capabilitiesChangedCallback; //!< Callback when PHY capabilities changed };