wifi: Add preamble detection and header field handling in PhyEntity

Preamble reception is still in WifiPhy (will be addressed in subsequent commits).
HE TB PPDU related actions in SpectrumWifiPhy should also be moved in following commits.
Payload reception part is also to be moved later on
This commit is contained in:
Rediet
2021-02-15 18:19:46 +01:00
parent aa1b68e980
commit 2fa6f9bb15
14 changed files with 1115 additions and 8 deletions

View File

@@ -24,6 +24,8 @@
#include "dsss-ppdu.h"
#include "wifi-psdu.h"
#include "wifi-phy.h" //only used for static mode constructor
#include "wifi-utils.h"
#include "ns3/simulator.h"
#include "ns3/log.h"
namespace ns3 {
@@ -160,6 +162,41 @@ DsssPhy::BuildPpdu (const WifiConstPsduMap & psdus, WifiTxVector txVector,
return Create<DsssPpdu> (psdus.begin ()->second, txVector, ppduDuration, uid);
}
PhyEntity::PhyFieldRxStatus
DsssPhy::DoEndReceiveField (WifiPpduField field, Ptr<Event> event)
{
NS_LOG_FUNCTION (this << field << *event);
if (field == WIFI_PPDU_FIELD_NON_HT_HEADER)
{
return EndReceiveHeader (event); //PHY header or short PHY header
}
return PhyEntity::DoEndReceiveField (field, event);
}
PhyEntity::PhyFieldRxStatus
DsssPhy::EndReceiveHeader (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
SnrPer snrPer = GetPhyHeaderSnrPer (WIFI_PPDU_FIELD_NON_HT_HEADER, event);
NS_LOG_DEBUG ("Long/Short PHY header: SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per);
PhyFieldRxStatus status (GetRandomValue () > snrPer.per);
if (status.isSuccess)
{
NS_LOG_DEBUG ("Received long/short PHY header");
if (!IsConfigSupported (event->GetPpdu ()))
{
status = PhyFieldRxStatus (false, UNSUPPORTED_SETTINGS, DROP);
}
}
else
{
NS_LOG_DEBUG ("Abort reception because long/short PHY header reception failed");
status.reason = L_SIG_FAILURE;
status.actionIfFailure = ABORT;
}
return status;
}
void
DsssPhy::InitializeModes (void)
{

View File

@@ -110,6 +110,9 @@ public:
static WifiMode GetDsssRate11Mbps (void);
private:
// Inherited
PhyFieldRxStatus DoEndReceiveField (WifiPpduField field, Ptr<Event> event) override;
/**
* \param txVector the transmission parameters
* \return the WifiMode used for the PHY header field
@@ -129,6 +132,15 @@ private:
*/
Time GetHeaderDuration (WifiTxVector txVector) const;
/**
* End receiving the header, perform DSSS-specific actions, and
* provide the status of the reception.
*
* \param event the event holding incoming PPDU's information
* \return status of the reception of the header
*/
PhyFieldRxStatus EndReceiveHeader (Ptr<Event> event);
static const PpduFormats m_dsssPpduFormats; //!< DSSS and HR/DSSS PPDU formats
}; //class DsssPhy

View File

@@ -22,7 +22,13 @@
#include "he-phy.h"
#include "he-ppdu.h"
#include "wifi-psdu.h"
#include "wifi-phy.h" //only used for static mode constructor
#include "wifi-phy.h"
#include "he-configuration.h"
#include "wifi-net-device.h"
#include "sta-wifi-mac.h"
#include "wifi-utils.h"
#include "ns3/uinteger.h"
#include "ns3/simulator.h"
#include "ns3/log.h"
#include "ns3/assert.h"
@@ -67,6 +73,7 @@ HePhy::HePhy (bool buildModeList /* = true */)
m_bssMembershipSelector = HE_PHY;
m_maxMcsIndexPerSs = 11;
m_maxSupportedMcsIndexPerSs = m_maxMcsIndexPerSs;
m_currentHeTbPpduUid = UINT64_MAX;
if (buildModeList)
{
BuildModeList ();
@@ -300,6 +307,139 @@ HePhy::BuildPpdu (const WifiConstPsduMap & psdus, WifiTxVector txVector,
return Create<HePpdu> (psdus, txVector, ppduDuration, band, uid);
}
Ptr<const WifiPsdu>
HePhy::GetAddressedPsduInPpdu (Ptr<const WifiPpdu> ppdu) const
{
if (ppdu->GetType () == WIFI_PPDU_TYPE_DL_MU || ppdu->GetType () == WIFI_PPDU_TYPE_UL_MU)
{
auto hePpdu = DynamicCast<const HePpdu> (ppdu);
NS_ASSERT (hePpdu);
return hePpdu->GetPsdu (GetBssColor (), GetStaId (ppdu));
}
return PhyEntity::GetAddressedPsduInPpdu (ppdu);
}
uint8_t
HePhy::GetBssColor (void) const
{
uint8_t bssColor = 0;
Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice> (m_wifiPhy->GetDevice ());
if (device)
{
Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration ();
if (heConfiguration)
{
UintegerValue bssColorAttribute;
heConfiguration->GetAttribute ("BssColor", bssColorAttribute);
bssColor = bssColorAttribute.Get ();
}
}
return bssColor;
}
uint16_t
HePhy::GetStaId (const Ptr<const WifiPpdu> ppdu) const
{
//TODO Move HE-specific logic here
return m_wifiPhy->GetStaId (ppdu);
}
PhyEntity::PhyFieldRxStatus
HePhy::ProcessSigA (Ptr<Event> event, PhyFieldRxStatus status)
{
NS_LOG_FUNCTION (this << *event << status);
//Notify end of SIG-A (in all cases)
HeSigAParameters params;
params.rssiW = GetRxPowerWForPpdu (event);
params.bssColor = event->GetTxVector ().GetBssColor ();
Simulator::ScheduleNow (&WifiPhy::NotifyEndOfHeSigA, GetPointer (m_wifiPhy), params);
if (status.isSuccess)
{
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
if (event->GetTxVector ().GetPreambleType () == WIFI_PREAMBLE_HE_TB)
{
m_currentHeTbPpduUid = ppdu->GetUid (); //to be able to correctly schedule start of OFDMA payload
}
//Check if PPDU is filtered only if the SIG-A content is supported
if (ppdu->GetType () == WIFI_PPDU_TYPE_DL_MU) //Final decision on content of DL MU is reported to end of SIG-B (unless the PPDU is filtered)
{
uint8_t bssColor = GetBssColor ();
if (bssColor != 0 && bssColor != event->GetTxVector ().GetBssColor ())
{
NS_LOG_DEBUG ("The BSS color of this DL MU PPDU does not match the device's. The PPDU is filtered.");
return PhyFieldRxStatus (false, FILTERED, ABORT);
}
}
else if (GetAddressedPsduInPpdu (ppdu))
{
//We are here because the SU or UL MU is addressed to the PPDU, so keep status to success
}
else
{
NS_ASSERT (ppdu->GetType () == WIFI_PPDU_TYPE_UL_MU);
NS_LOG_DEBUG ("No PSDU addressed to that PHY in the received MU PPDU. The PPDU is filtered.");
return PhyFieldRxStatus (false, FILTERED, ABORT);
}
}
return status;
}
PhyEntity::PhyFieldRxStatus
HePhy::ProcessSigB (Ptr<Event> event, PhyFieldRxStatus status)
{
NS_LOG_FUNCTION (this << *event << status);
if (status.isSuccess)
{
//Check if PPDU is filtered only if the SIG-B content is supported (not explicitly stated but assumed based on behavior for SIG-A)
if (!GetAddressedPsduInPpdu (event->GetPpdu ()))
{
NS_LOG_DEBUG ("No PSDU addressed to that PHY in the received MU PPDU. The PPDU is filtered.");
return PhyFieldRxStatus (false, FILTERED, ABORT);
}
}
return status;
}
bool
HePhy::IsConfigSupported (Ptr<const WifiPpdu> ppdu) const
{
WifiTxVector txVector = ppdu->GetTxVector ();
uint16_t staId = GetStaId (ppdu);
WifiMode txMode = txVector.GetMode (staId);
uint8_t nss = txVector.GetNssMax ();
if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_MU)
{
for (auto info : txVector.GetHeMuUserInfoMap ())
{
if (info.first == staId)
{
nss = info.second.nss; //no need to look at other PSDUs
break;
}
}
}
if (nss > m_wifiPhy->GetMaxSupportedRxSpatialStreams ())
{
NS_LOG_DEBUG ("Packet reception could not be started because not enough RX antennas");
return false;
}
if (!IsModeSupported (txMode))
{
NS_LOG_DEBUG ("Drop packet because it was sent using an unsupported mode (" << txVector.GetMode () << ")");
return false;
}
return true;
}
uint64_t
HePhy::GetCurrentHeTbPpduUid (void) const
{
return m_currentHeTbPpduUid;
}
void
HePhy::InitializeModes (void)
{

View File

@@ -73,6 +73,21 @@ public:
Time GetSigBDuration (WifiTxVector txVector) const override;
virtual Ptr<WifiPpdu> BuildPpdu (const WifiConstPsduMap & psdus, WifiTxVector txVector,
Time ppduDuration, WifiPhyBand band, uint64_t uid) const override;
Ptr<const WifiPsdu> GetAddressedPsduInPpdu (Ptr<const WifiPpdu> ppdu) const override;
/**
* \return the BSS color of this PHY.
*/
uint8_t GetBssColor (void) const;
/**
* Return the STA ID that has been assigned to the station this PHY belongs to.
* This is typically called for MU PPDUs, in order to pick the correct PSDU.
*
* \param ppdu the PPDU for which the STA ID is requested
* \return the STA ID
*/
uint16_t GetStaId (const Ptr<const WifiPpdu> ppdu) const;
/**
* \param ppduDuration the duration of the HE TB PPDU
@@ -96,6 +111,11 @@ public:
*/
Time CalculateNonOfdmaDurationForHeTb (WifiTxVector txVector) const;
/**
* \return the UID of the HE TB PPDU being received
*/
uint64_t GetCurrentHeTbPpduUid (void) const;
/**
* Initialize all HE modes.
*/
@@ -182,6 +202,14 @@ public:
*/
static WifiMode GetHeMcs11 (void);
protected:
// Inherited
PhyFieldRxStatus ProcessSigA (Ptr<Event> event, PhyFieldRxStatus status) override;
PhyFieldRxStatus ProcessSigB (Ptr<Event> event, PhyFieldRxStatus status) override;
virtual bool IsConfigSupported (Ptr<const WifiPpdu> ppdu) const override;
uint64_t m_currentHeTbPpduUid; //!< UID of the HE TB PPDU being received
private:
// Inherited
virtual void BuildModeList (void) override;

View File

@@ -22,7 +22,8 @@
#include "ht-phy.h"
#include "ht-ppdu.h"
#include "wifi-psdu.h"
#include "wifi-phy.h" //only used for static mode constructor
#include "wifi-phy.h"
#include "wifi-utils.h"
#include "ns3/log.h"
#include "ns3/assert.h"
@@ -370,6 +371,76 @@ HtPhy::BuildPpdu (const WifiConstPsduMap & psdus, WifiTxVector txVector, Time pp
return Create<HtPpdu> (psdus.begin ()->second, txVector, ppduDuration, band, uid);
}
PhyEntity::PhyFieldRxStatus
HtPhy::DoEndReceiveField (WifiPpduField field, Ptr<Event> event)
{
NS_LOG_FUNCTION (this << field << *event);
switch (field)
{
case WIFI_PPDU_FIELD_HT_SIG:
return EndReceiveHtSig (event);
case WIFI_PPDU_FIELD_TRAINING:
return PhyFieldRxStatus (true); //always consider that training has been correctly received
case WIFI_PPDU_FIELD_NON_HT_HEADER:
NS_ASSERT (event->GetTxVector ().GetPreambleType () != WIFI_PREAMBLE_HT_GF);
//no break so as to go to OfdmPhy for processing
default:
return OfdmPhy::DoEndReceiveField (field, event);
}
}
PhyEntity::PhyFieldRxStatus
HtPhy::EndReceiveHtSig (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
NS_ASSERT (IsHt (event->GetTxVector ().GetPreambleType ()));
SnrPer snrPer = GetPhyHeaderSnrPer (WIFI_PPDU_FIELD_HT_SIG, event);
NS_LOG_DEBUG ("HT-SIG: SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per);
PhyFieldRxStatus status (GetRandomValue () > snrPer.per);
if (status.isSuccess)
{
NS_LOG_DEBUG ("Received HT-SIG");
if (!IsAllConfigSupported (WIFI_PPDU_FIELD_HT_SIG, event->GetPpdu ()))
{
status = PhyFieldRxStatus (false, UNSUPPORTED_SETTINGS, DROP);
}
}
else
{
NS_LOG_DEBUG ("Drop packet because HT-SIG reception failed");
status.reason = HT_SIG_FAILURE;
status.actionIfFailure = DROP;
}
return status;
}
bool
HtPhy::IsAllConfigSupported (WifiPpduField field, Ptr<const WifiPpdu> ppdu) const
{
if (field == WIFI_PPDU_FIELD_NON_HT_HEADER)
{
return true; //wait till reception of HT-SIG (or SIG-A) to make decision
}
return OfdmPhy::IsAllConfigSupported (field, ppdu);
}
bool
HtPhy::IsConfigSupported (Ptr<const WifiPpdu> ppdu) const
{
WifiTxVector txVector = ppdu->GetTxVector ();
if (txVector.GetNss () > m_wifiPhy->GetMaxSupportedRxSpatialStreams ())
{
NS_LOG_DEBUG ("Packet reception could not be started because not enough RX antennas");
return false;
}
if (!IsModeSupported (txVector.GetMode ()))
{
NS_LOG_DEBUG ("Drop packet because it was sent using an unsupported mode (" << txVector.GetMode () << ")");
return false;
}
return true;
}
void
HtPhy::InitializeModes (void)
{

View File

@@ -343,6 +343,11 @@ public:
static WifiMode GetHtMcs31 (void);
protected:
// Inherited
virtual PhyFieldRxStatus DoEndReceiveField (WifiPpduField field, Ptr<Event> event) override;
virtual bool IsAllConfigSupported (WifiPpduField field, Ptr<const WifiPpdu> ppdu) const override;
virtual bool IsConfigSupported (Ptr<const WifiPpdu> ppdu) const override;
/**
* Build mode list.
* Should be redone whenever the maximum MCS index per spatial stream
@@ -367,6 +372,15 @@ protected:
uint8_t m_bssMembershipSelector; //!< the BSS membership selector
private:
/**
* End receiving the HT-SIG, perform HT-specific actions, and
* provide the status of the reception.
*
* \param event the event holding incoming PPDU's information
* \return status of the reception of the HT-SIG
*/
PhyFieldRxStatus EndReceiveHtSig (Ptr<Event> event);
uint8_t m_maxSupportedNss; //!< Maximum supported number of spatial streams (used to build HT MCS indices)
static const PpduFormats m_htPpduFormats; //!< HT PPDU formats

View File

@@ -23,9 +23,10 @@
#include "ofdm-phy.h"
#include "ofdm-ppdu.h"
#include "wifi-psdu.h"
#include "wifi-phy.h" //only used for static mode constructor
#include "wifi-phy.h"
#include "wifi-utils.h"
#include "ns3/simulator.h"
#include "ns3/log.h"
#include "ns3/assert.h"
namespace ns3 {
@@ -236,6 +237,63 @@ OfdmPhy::BuildPpdu (const WifiConstPsduMap & psdus, WifiTxVector txVector,
return Create<OfdmPpdu> (psdus.begin ()->second, txVector, band, uid);
}
PhyEntity::PhyFieldRxStatus
OfdmPhy::DoEndReceiveField (WifiPpduField field, Ptr<Event> event)
{
NS_LOG_FUNCTION (this << field << *event);
if (field == WIFI_PPDU_FIELD_NON_HT_HEADER)
{
return EndReceiveHeader (event); //L-SIG
}
return PhyEntity::DoEndReceiveField (field, event);
}
PhyEntity::PhyFieldRxStatus
OfdmPhy::EndReceiveHeader (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
SnrPer snrPer = GetPhyHeaderSnrPer (WIFI_PPDU_FIELD_NON_HT_HEADER, event);
NS_LOG_DEBUG ("L-SIG: SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per);
PhyFieldRxStatus status (GetRandomValue () > snrPer.per);
if (status.isSuccess)
{
NS_LOG_DEBUG ("Received non-HT PHY header");
if (!IsAllConfigSupported (WIFI_PPDU_FIELD_NON_HT_HEADER, event->GetPpdu ()))
{
status = PhyFieldRxStatus (false, UNSUPPORTED_SETTINGS, DROP);
}
}
else
{
NS_LOG_DEBUG ("Abort reception because non-HT PHY header reception failed");
status.reason = L_SIG_FAILURE;
status.actionIfFailure = ABORT;
}
return status;
}
bool
OfdmPhy::IsChannelWidthSupported (Ptr<const WifiPpdu> ppdu) const
{
uint16_t channelWidth = ppdu->GetTxVector ().GetChannelWidth ();
if ((channelWidth >= 40) && (channelWidth > m_wifiPhy->GetChannelWidth ()))
{
NS_LOG_DEBUG ("Packet reception could not be started because not enough channel width (" << channelWidth << " vs " << m_wifiPhy->GetChannelWidth () << ")");
return false;
}
return true;
}
bool
OfdmPhy::IsAllConfigSupported (WifiPpduField /* field */, Ptr<const WifiPpdu> ppdu) const
{
if (!IsChannelWidthSupported (ppdu))
{
return false;
}
return IsConfigSupported (ppdu);
}
void
OfdmPhy::InitializeModes (void)
{

View File

@@ -258,11 +258,15 @@ public:
static WifiMode GetOfdmRate13_5MbpsBW5MHz (void);
protected:
// Inherited
virtual PhyFieldRxStatus DoEndReceiveField (WifiPpduField field, Ptr<Event> event) override;
/**
* \param txVector the transmission parameters
* \return the WifiMode used for the SIGNAL field
*/
virtual WifiMode GetHeaderMode (WifiTxVector txVector) const;
/**
* \param txVector the transmission parameters
* \return the duration of the preamble field
@@ -286,6 +290,32 @@ protected:
*/
Time GetSignalExtension (WifiPhyBand band) const;
/**
* End receiving the header, perform OFDM-specific actions, and
* provide the status of the reception.
*
* \param event the event holding incoming PPDU's information
* \return status of the reception of the header
*/
PhyFieldRxStatus EndReceiveHeader (Ptr<Event> event);
/**
* Checks if the PPDU's bandwidth is supported by the PHY.
*
* \param ppdu the received PPDU
* \return \c true if supported, \c false otherwise
*/
virtual bool IsChannelWidthSupported (Ptr<const WifiPpdu> ppdu) const;
/**
* Checks if the signaled configuration (including bandwidth)
* is supported by the PHY.
*
* \param field the current PPDU field (SIG used for checking config)
* \param ppdu the received PPDU
* \return \c true if supported, \c false otherwise
*/
virtual bool IsAllConfigSupported (WifiPpduField field, Ptr<const WifiPpdu> ppdu) const;
private:
static const PpduFormats m_ofdmPpduFormats; //!< OFDM PPDU formats
}; //class OfdmPhy

View File

@@ -21,7 +21,11 @@
*/
#include "phy-entity.h"
#include "wifi-phy.h"
#include "wifi-psdu.h"
#include "preamble-detection-model.h"
#include "wifi-utils.h"
#include "ns3/simulator.h"
#include "ns3/log.h"
#include "ns3/assert.h"
#include <algorithm>
@@ -30,6 +34,34 @@ namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("PhyEntity");
std::ostream & operator << (std::ostream &os, const PhyEntity::PhyRxFailureAction &action)
{
switch (action)
{
case PhyEntity::DROP:
return (os << "DROP");
case PhyEntity::ABORT:
return (os << "ABORT");
case PhyEntity::IGNORE:
return (os << "IGNORE");
default:
NS_FATAL_ERROR ("Unknown action");
return (os << "unknown");
}
}
std::ostream & operator << (std::ostream &os, const PhyEntity::PhyFieldRxStatus &status)
{
if (status.isSuccess)
{
return os << "success";
}
else
{
return os << "failure (" << status.reason << "/" << status.actionIfFailure << ")";
}
}
/*******************************************************
* Abstract base class for PHY entities
*******************************************************/
@@ -39,6 +71,14 @@ PhyEntity::~PhyEntity ()
m_modeList.clear ();
}
void
PhyEntity::SetOwner (Ptr<WifiPhy> wifiPhy)
{
NS_LOG_FUNCTION (this << wifiPhy);
m_wifiPhy = wifiPhy;
m_state = m_wifiPhy->m_state;
}
bool
PhyEntity::IsModeSupported (WifiMode mode) const
{
@@ -146,6 +186,12 @@ PhyEntity::CalculatePhyPreambleAndHeaderDuration (WifiTxVector txVector) const
return duration;
}
Ptr<const WifiPsdu>
PhyEntity::GetAddressedPsduInPpdu (Ptr<const WifiPpdu> ppdu) const
{
return ppdu->GetPsdu ();
}
PhyEntity::PhyHeaderSections
PhyEntity::GetPhyHeaderSections (WifiTxVector txVector, Time ppduStart) const
{
@@ -173,4 +219,308 @@ PhyEntity::BuildPpdu (const WifiConstPsduMap & psdus, WifiTxVector txVector,
return Create<WifiPpdu> (psdus.begin ()->second, txVector); //should be overloaded
}
Time
PhyEntity::GetDurationUpToField (WifiPpduField field, WifiTxVector txVector) const
{
if (field == WIFI_PPDU_FIELD_DATA) //this field is not in the map returned by GetPhyHeaderSections
{
return CalculatePhyPreambleAndHeaderDuration (txVector);
}
const auto & sections = GetPhyHeaderSections (txVector, NanoSeconds (0));
auto it = sections.find (field);
NS_ASSERT (it != sections.end ());
const auto & startStopTimes = it->second.first;
return startStopTimes.first; //return the start time of field relatively to the beginning of the PPDU
}
PhyEntity::SnrPer
PhyEntity::GetPhyHeaderSnrPer (WifiPpduField field, Ptr<Event> event) const
{
uint16_t measurementChannelWidth = m_wifiPhy->GetMeasurementChannelWidth (event->GetPpdu ());
return m_wifiPhy->m_interference.CalculatePhyHeaderSnrPer (event, measurementChannelWidth, m_wifiPhy->GetBand (measurementChannelWidth),
field);
}
void
PhyEntity::StartReceiveField (WifiPpduField field, Ptr<Event> event)
{
NS_LOG_FUNCTION (this << field << *event);
NS_ASSERT (m_wifiPhy); //no sense if no owner WifiPhy instance
NS_ASSERT (m_wifiPhy->m_endPhyRxEvent.IsExpired ()
|| m_wifiPhy->m_currentPreambleEvents.size () > 1); //TODO find a better way of handling multiple preambles until synching on one after detection period
//Handle special cases of preamble and data reception (TODO improve this logic later on)
if (field == WIFI_PPDU_FIELD_PREAMBLE)
{
DoStartReceivePreamble (event);
return;
}
if (field == WIFI_PPDU_FIELD_DATA)
{
//TODO improve this logic later on
//Hand over to WifiPhy for data processing
m_wifiPhy->StartReceivePayload (event);
return;
}
bool supported = DoStartReceiveField (field, event);
NS_ABORT_MSG_IF (!supported, "Unknown field " << field << " for this PHY entity"); //TODO see what to do if not supported
Time duration = GetDuration (field, event->GetTxVector ());
m_wifiPhy->m_endPhyRxEvent = Simulator::Schedule (duration, &PhyEntity::EndReceiveField, this, field, event);
m_state->SwitchMaybeToCcaBusy (duration); //keep in CCA busy state up to reception of Data (will then switch to RX)
}
void
PhyEntity::EndReceiveField (WifiPpduField field, Ptr<Event> event)
{
NS_LOG_FUNCTION (this << field << *event);
NS_ASSERT (m_wifiPhy); //no sense if no owner WifiPhy instance
NS_ASSERT (m_wifiPhy->m_endPhyRxEvent.IsExpired ());
PhyFieldRxStatus status = DoEndReceiveField (field, event);
WifiTxVector txVector = event->GetTxVector ();
if (status.isSuccess) //move to next field if reception succeeded
{
StartReceiveField (GetNextField (field, txVector.GetPreambleType ()), event);
}
else
{
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
switch (status.actionIfFailure)
{
case ABORT:
//Abort reception, but consider medium as busy
if (status.reason == FILTERED)
{
//PHY-RXSTART is immediately followed by PHY-RXEND (Filtered)
m_wifiPhy->m_phyRxPayloadBeginTrace (txVector, NanoSeconds (0)); //this callback (equivalent to PHY-RXSTART primitive) is also triggered for filtered PPDUs
}
AbortCurrentReception (status.reason);
if (event->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
{
m_wifiPhy->MaybeCcaBusyDuration (m_wifiPhy->GetMeasurementChannelWidth (ppdu));
}
break;
case DROP:
//Notify drop, keep in CCA busy, and perform same processing as IGNORE case
m_wifiPhy->NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), status.reason);
m_state->SwitchMaybeToCcaBusy (GetRemainingDurationAfterField (ppdu, field)); //keep in CCA busy state till the end
case IGNORE:
//Keep in Rx state and reset at end
m_wifiPhy->m_endRxEvents.push_back (Simulator::Schedule (GetRemainingDurationAfterField (ppdu, field),
&PhyEntity::ResetReceive, this, event));
break;
default:
NS_FATAL_ERROR ("Unknown action in case of failure");
}
}
}
Time
PhyEntity::GetRemainingDurationAfterField (Ptr<const WifiPpdu> ppdu, WifiPpduField field) const
{
WifiTxVector txVector = ppdu->GetTxVector ();
return ppdu->GetTxDuration () - (GetDurationUpToField (field, txVector) + GetDuration (field, txVector));
}
bool
PhyEntity::DoStartReceiveField (WifiPpduField field, Ptr<Event> event)
{
NS_LOG_FUNCTION (this << field << *event);
NS_ASSERT (field != WIFI_PPDU_FIELD_PREAMBLE && field != WIFI_PPDU_FIELD_DATA); //handled apart for the time being
auto ppduFormats = GetPpduFormats ();
auto itFormat = ppduFormats.find (event->GetPpdu ()->GetPreamble ());
if (itFormat != ppduFormats.end ())
{
auto itField = std::find (itFormat->second.begin (), itFormat->second.end (), field);
if (itField != itFormat->second.end ())
{
return true; //supported field so we can start receiving
}
}
return false; //unsupported otherwise
}
PhyEntity::PhyFieldRxStatus
PhyEntity::DoEndReceiveField (WifiPpduField field, Ptr<Event> event)
{
NS_LOG_FUNCTION (this << field << *event);
NS_ASSERT (field != WIFI_PPDU_FIELD_DATA); //handled apart for the time being
if (field == WIFI_PPDU_FIELD_PREAMBLE)
{
return DoEndReceivePreamble (event);
}
return PhyFieldRxStatus (false); //failed reception by default
}
bool
PhyEntity::DoStartReceivePreamble (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
//TODO handle special cases in WifiPhy::StartReceivePreamble
StartPreambleDetectionPeriod (event);
return true;
}
PhyEntity::PhyFieldRxStatus
PhyEntity::DoEndReceivePreamble (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
NS_ASSERT (m_wifiPhy->m_currentPreambleEvents.size () == 1); //Synched on one after detection period
return PhyFieldRxStatus (true); //always consider that preamble has been correctly received if preamble detection was OK
}
void
PhyEntity::StartPreambleDetectionPeriod (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
NS_LOG_DEBUG ("Sync to signal (power=" << GetRxPowerWForPpdu (event) << "W)");
m_wifiPhy->m_interference.NotifyRxStart (); //We need to notify it now so that it starts recording events
//TODO see if preamble detection events cannot be ported here
m_wifiPhy->m_endPreambleDetectionEvents.push_back (Simulator::Schedule (m_wifiPhy->GetPreambleDetectionDuration (), &PhyEntity::EndPreambleDetectionPeriod, this, event));
}
void
PhyEntity::EndPreambleDetectionPeriod (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
NS_ASSERT (!m_wifiPhy->IsStateRx ());
NS_ASSERT (m_wifiPhy->m_endPhyRxEvent.IsExpired ()); //since end of preamble reception is scheduled by this method upon success
//calculate PER on the measurement channel for PHY headers
uint16_t measurementChannelWidth = m_wifiPhy->GetMeasurementChannelWidth (event->GetPpdu ());
auto measurementBand = m_wifiPhy->GetBand (measurementChannelWidth);
double maxRxPowerW = -1; //in case current event may not be sent on measurement channel (rxPowerW would be equal to 0)
Ptr<Event> maxEvent;
NS_ASSERT (!m_wifiPhy->m_currentPreambleEvents.empty ());
for (auto preambleEvent : m_wifiPhy->m_currentPreambleEvents)
{
double rxPowerW = preambleEvent.second->GetRxPowerW (measurementBand);
if (rxPowerW > maxRxPowerW)
{
maxRxPowerW = rxPowerW;
maxEvent = preambleEvent.second;
}
}
NS_ASSERT (maxEvent != 0);
if (maxEvent != event)
{
NS_LOG_DEBUG ("Receiver got a stronger packet with UID " << maxEvent->GetPpdu ()->GetUid () << " during preamble detection: drop packet with UID " << event->GetPpdu ()->GetUid ());
m_wifiPhy->NotifyRxDrop (GetAddressedPsduInPpdu (event->GetPpdu ()), BUSY_DECODING_PREAMBLE);
auto it = m_wifiPhy->m_currentPreambleEvents.find (std::make_pair (event->GetPpdu ()->GetUid (), event->GetPpdu ()->GetPreamble ()));
m_wifiPhy->m_currentPreambleEvents.erase (it);
//This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to the power at the start of the PPDU
m_wifiPhy->m_interference.NotifyRxEnd (maxEvent->GetStartTime ());
//Make sure InterferenceHelper keeps recording events
m_wifiPhy->m_interference.NotifyRxStart ();
return;
}
m_wifiPhy->m_currentEvent = event;
double snr = m_wifiPhy->m_interference.CalculateSnr (m_wifiPhy->m_currentEvent, measurementChannelWidth, 1, measurementBand);
NS_LOG_DEBUG ("SNR(dB)=" << RatioToDb (snr) << " at end of preamble detection period");
if ((!m_wifiPhy->m_preambleDetectionModel && maxRxPowerW > 0.0)
|| (m_wifiPhy->m_preambleDetectionModel && m_wifiPhy->m_preambleDetectionModel->IsPreambleDetected (m_wifiPhy->m_currentEvent->GetRxPowerW (measurementBand), snr, measurementChannelWidth)))
{
for (auto & endPreambleDetectionEvent : m_wifiPhy->m_endPreambleDetectionEvents)
{
endPreambleDetectionEvent.Cancel ();
}
m_wifiPhy->m_endPreambleDetectionEvents.clear ();
for (auto it = m_wifiPhy->m_currentPreambleEvents.begin (); it != m_wifiPhy->m_currentPreambleEvents.end (); )
{
if (it->second != m_wifiPhy->m_currentEvent)
{
NS_LOG_DEBUG ("Drop packet with UID " << it->first.first << " and preamble " << it->first.second << " arrived at time " << it->second->GetStartTime ());
WifiPhyRxfailureReason reason;
if (m_wifiPhy->m_currentEvent->GetPpdu ()->GetUid () > it->first.first)
{
reason = PREAMBLE_DETECTION_PACKET_SWITCH;
//This is needed to cleanup the m_firstPowerPerBand so that the first power corresponds to the power at the start of the PPDU
m_wifiPhy->m_interference.NotifyRxEnd (m_wifiPhy->m_currentEvent->GetStartTime ());
}
else
{
reason = BUSY_DECODING_PREAMBLE;
}
m_wifiPhy->NotifyRxDrop (GetAddressedPsduInPpdu (it->second->GetPpdu ()), reason);
it = m_wifiPhy->m_currentPreambleEvents.erase (it);
}
else
{
++it;
}
}
//Make sure InterferenceHelper keeps recording events
m_wifiPhy->m_interference.NotifyRxStart ();
m_wifiPhy->NotifyRxBegin (GetAddressedPsduInPpdu (m_wifiPhy->m_currentEvent->GetPpdu ()), m_wifiPhy->m_currentEvent->GetRxPowerWPerBand ());
m_wifiPhy->m_timeLastPreambleDetected = Simulator::Now ();
//Continue receiving preamble
Time durationTillEnd = GetDuration (WIFI_PPDU_FIELD_PREAMBLE, event->GetTxVector ()) - m_wifiPhy->GetPreambleDetectionDuration ();
m_state->SwitchMaybeToCcaBusy (durationTillEnd); //will be prolonged by next field
m_wifiPhy->m_endPhyRxEvent = Simulator::Schedule (durationTillEnd, &PhyEntity::EndReceiveField, this, WIFI_PPDU_FIELD_PREAMBLE, event);
}
else
{
NS_LOG_DEBUG ("Drop packet because PHY preamble detection failed");
// Like CCA-SD, CCA-ED is governed by the 4 us CCA window to flag CCA-BUSY
// for any received signal greater than the CCA-ED threshold.
m_wifiPhy->DropPreambleEvent (m_wifiPhy->m_currentEvent->GetPpdu (), PREAMBLE_DETECT_FAILURE, m_wifiPhy->m_currentEvent->GetEndTime (), m_wifiPhy->GetMeasurementChannelWidth (m_wifiPhy->m_currentEvent->GetPpdu ()));
if (m_wifiPhy->m_currentPreambleEvents.empty ())
{
//Do not erase events if there are still pending preamble events to be processed
m_wifiPhy->m_interference.NotifyRxEnd (Simulator::Now ());
}
m_wifiPhy->m_currentEvent = 0;
//Cancel preamble reception
m_wifiPhy->m_endPhyRxEvent.Cancel ();
}
}
bool
PhyEntity::IsConfigSupported (Ptr<const WifiPpdu> ppdu) const
{
WifiMode txMode = ppdu->GetTxVector ().GetMode ();
if (!IsModeSupported (txMode))
{
NS_LOG_DEBUG ("Drop packet because it was sent using an unsupported mode (" << txMode << ")");
return false;
}
return true;
}
void
PhyEntity::AbortCurrentReception (WifiPhyRxfailureReason reason)
{
NS_LOG_FUNCTION (this << reason);
//TODO cancel some events here later on
m_wifiPhy->AbortCurrentReception (reason);
}
void
PhyEntity::ResetReceive (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
NS_ASSERT (event->GetEndTime () == Simulator::Now ()); //TODO: overload for UL MU
m_wifiPhy->ResetReceive (event);
}
double
PhyEntity::GetRandomValue (void) const
{
return m_wifiPhy->m_random->GetValue ();
}
double
PhyEntity::GetRxPowerWForPpdu (Ptr<Event> event) const
{
return event->GetRxPowerW (m_wifiPhy->GetBand (m_wifiPhy->GetMeasurementChannelWidth (event->GetPpdu ())));
}
} //namespace ns3

View File

@@ -24,10 +24,13 @@
#define PHY_ENTITY_H
#include "wifi-mpdu-type.h"
#include "wifi-tx-vector.h"
#include "wifi-phy-band.h"
#include "wifi-ppdu.h"
#include "ns3/event-id.h"
#include "ns3/simple-ref-count.h"
#include "ns3/nstime.h"
#include <list>
#include <map>
/**
@@ -39,6 +42,12 @@
namespace ns3 {
class WifiPsdu;
class WifiPhy;
class InterferenceHelper;
class Event;
class WifiPhyStateHelper;
class WifiPsdu;
class WifiPpdu;
/**
* \brief Abstract class for PHY entities
@@ -51,6 +60,43 @@ class WifiPsdu;
class PhyEntity : public SimpleRefCount<PhyEntity>
{
public:
/**
* Action to perform in case of RX failure.
*/
enum PhyRxFailureAction
{
DROP = 0, //!< drop PPDU and set CCA_BUSY
ABORT, //!< abort reception of PPDU
IGNORE //!< ignore the reception
};
/**
* Status of the reception of the PPDU field.
*/
struct PhyFieldRxStatus
{
/* *NS_CHECK_STYLE_OFF* */
bool isSuccess {true}; //!< outcome (\c true if success) of the reception
WifiPhyRxfailureReason reason {UNKNOWN}; //!< failure reason
PhyRxFailureAction actionIfFailure {DROP}; //!< action to perform in case of failure \see PhyRxFailureAction
/**
* Constructor setting outcome of reception.
*
* \param s \c true if success
*/
PhyFieldRxStatus (bool s) : isSuccess (s) {};
/**
* Constructor.
*
* \param s \c true if success
* \param r reason of failure
* \param a action to perform in case of failure
*/
PhyFieldRxStatus (bool s, WifiPhyRxfailureReason r, PhyRxFailureAction a) : isSuccess (s), reason (r), actionIfFailure (a) {};
/* *NS_CHECK_STYLE_ON* */
};
/**
* A struct for both SNR and PER
*/
@@ -76,6 +122,13 @@ public:
*/
virtual ~PhyEntity ();
/**
* Set the WifiPhy owning this PHY entity.
*
* \param wifiPhy the WifiPhy owning this PHY entity
*/
void SetOwner (Ptr<WifiPhy> wifiPhy);
/**
* Check if the WifiMode is supported.
*
@@ -229,6 +282,59 @@ public:
virtual Ptr<WifiPpdu> BuildPpdu (const WifiConstPsduMap & psdus, WifiTxVector txVector,
Time ppduDuration, WifiPhyBand band, uint64_t uid) const;
/**
* Get the duration of the PPDU up to (but excluding) the given field.
*
* \param field the considered PPDU field
* \param txVector the transmission parameters
* \return the duration from the beginning of the PPDU up to the field
*/
Time GetDurationUpToField (WifiPpduField field, WifiTxVector txVector) const;
/**
* Get the remaining duration of the PPDU after the end of the given field.
*
* \param field the considered PPDU field
* \param ppdu the received PPDU
* \return the remaining duration of the PPDU after the end of to the field
*/
Time GetRemainingDurationAfterField (Ptr<const WifiPpdu> ppdu, WifiPpduField field) const;
/**
* Get the PSDU addressed to that PHY in a PPDU (useful for MU PPDU).
*
* \param ppdu the PPDU to extract the PSDU from
* \return the PSDU addressed to that PHY
*/
virtual Ptr<const WifiPsdu> GetAddressedPsduInPpdu (Ptr<const WifiPpdu> ppdu) const;
/**
* Start receiving a given field.
*
* This method will call the DoStartReceiveField (which will should
* be overridden by child classes).
* EndReceiveField is also scheduled after the duration of the field
* (except for the special case of preambles \see DoStartReceivePreamble).
* The PHY is kept in CCA busy during the reception of the field (except for
* data field which should be in RX).
*
* \param field the starting PPDU field
* \param event the event holding incoming PPDU's information
*/
void StartReceiveField (WifiPpduField field, Ptr<Event> event);
/**
* End receiving a given field.
*
* This method will call the DoEndReceiveField (which will should
* be overridden by child classes) to obtain the outcome of the reception.
* In case of success, reception of the next field is triggered.
* In case of failure, the indications in the returned \see PhyFieldRxStatus
* are performed.
*
* \param field the ending PPDU field
* \param event the event holding incoming PPDU's information
*/
void EndReceiveField (WifiPpduField field, Ptr<Event> event);
protected:
/**
* A map of PPDU field elements per preamble type.
@@ -246,9 +352,131 @@ protected:
*/
virtual const PpduFormats & GetPpduFormats (void) const = 0;
std::list<WifiMode> m_modeList; //!< the list of supported modes
/**
* Start receiving a given field, perform amendment-specific actions, and
* signify if it is supported.
*
* \param field the starting PPDU field
* \param event the event holding incoming PPDU's information
* \return \c true if the field is supported, \c false otherwise
*/
virtual bool DoStartReceiveField (WifiPpduField field, Ptr<Event> event);
/**
* End receiving a given field, perform amendment-specific actions, and
* provide the status of the reception.
*
* \param field the ending PPDU field
* \param event the event holding incoming PPDU's information
* \return status of the reception of the PPDU field
*/
virtual PhyFieldRxStatus DoEndReceiveField (WifiPpduField field, Ptr<Event> event);
/**
* Start receiving the preamble, perform amendment-specific actions, and
* signify if it is supported.
*
* This method triggers the start of the preamble detection period (\see
* StartPreambleDetectionPeriod).
*
* \param event the event holding incoming PPDU's information
* \return \c true if the preamble is supported, \c false otherwise
*/
virtual bool DoStartReceivePreamble (Ptr<Event> event);
/**
* End receiving the preamble, perform amendment-specific actions, and
* provide the status of the reception.
*
* \param event the event holding incoming PPDU's information
* \return status of the reception of the preamble
*/
virtual PhyFieldRxStatus DoEndReceivePreamble (Ptr<Event> event);
/**
* Start the preamble detection period.
*
* \param event the event holding incoming PPDU's information
*/
void StartPreambleDetectionPeriod (Ptr<Event> event);
/**
* End the preamble detection period.
*
* The PHY will focus on the strongest PPDU and drop others.
* In addition, in case of successful detection, the end of the
* preamble reception is triggered (\see DoEndReceivePreamble).
*
* \param event the event holding incoming PPDU's information
*/
void EndPreambleDetectionPeriod (Ptr<Event> event);
/**
* Checks if the signaled configuration (excluding bandwidth)
* is supported by the PHY.
*
* \param ppdu the received PPDU
* \return \c true if supported, \c false otherwise
*/
virtual bool IsConfigSupported (Ptr<const WifiPpdu> ppdu) const;
/**
* Abort the current reception.
*
* \param reason the reason the reception is aborted
*/
void AbortCurrentReception (WifiPhyRxfailureReason reason);
/**
* Reset PHY at the end of the PPDU under reception after it has failed the PHY header.
*
* \param event the event holding incoming PPDU's information
*/
void ResetReceive (Ptr<Event> event);
/**
* Obtain a random value from the WifiPhy's generator.
* Wrapper used by child classes.
*
* \return a uniform random value
*/
double GetRandomValue (void) const;
/**
* Obtain the SNR and PER of the PPDU field from the WifiPhy's InterferenceHelper class.
* Wrapper used by child classes.
*
* \param field the PPDU field
* \param event the event holding incoming PPDU's information
* \return the SNR and PER
*/
SnrPer GetPhyHeaderSnrPer (WifiPpduField field, Ptr<Event> event) const;
/**
* Obtain the received power (W) for a given band.
* Wrapper used by child classes.
*
* \param event the event holding incoming PPDU's information
* \return the received power (W) for the event over a given band
*/
double GetRxPowerWForPpdu (Ptr<Event> event) const;
Ptr<WifiPhy> m_wifiPhy; //!< Pointer to the owning WifiPhy
Ptr<WifiPhyStateHelper> m_state; //!< Pointer to WifiPhyStateHelper of the WifiPhy (to make it reachable for child classes)
std::list<WifiMode> m_modeList; //!< the list of supported modes
}; //class PhyEntity
/**
* \brief Stream insertion operator.
*
* \param os the stream
* \param action the action to perform in case of failure
* \returns a reference to the stream
*/
std::ostream& operator<< (std::ostream& os, const PhyEntity::PhyRxFailureAction &action);
/**
* \brief Stream insertion operator.
*
* \param os the stream
* \param status the status of the reception of a PPDU field
* \returns a reference to the stream
*/
std::ostream& operator<< (std::ostream& os, const PhyEntity::PhyFieldRxStatus &status);
} //namespace ns3
#endif /* PHY_ENTITY_H */

View File

@@ -23,6 +23,7 @@
#include "vht-ppdu.h"
#include "wifi-psdu.h"
#include "wifi-phy.h" //only used for static mode constructor
#include "wifi-utils.h"
#include "ns3/log.h"
#include "ns3/assert.h"
@@ -220,6 +221,99 @@ VhtPhy::BuildPpdu (const WifiConstPsduMap & psdus, WifiTxVector txVector,
return Create<VhtPpdu> (psdus.begin ()->second, txVector, ppduDuration, band, uid);
}
PhyEntity::PhyFieldRxStatus
VhtPhy::DoEndReceiveField (WifiPpduField field, Ptr<Event> event)
{
NS_LOG_FUNCTION (this << field << *event);
switch (field)
{
case WIFI_PPDU_FIELD_SIG_A:
return EndReceiveSigA (event);
case WIFI_PPDU_FIELD_SIG_B:
return EndReceiveSigB (event);
default:
return HtPhy::DoEndReceiveField (field, event);
}
}
PhyEntity::PhyFieldRxStatus
VhtPhy::EndReceiveSigA (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
NS_ASSERT (event->GetTxVector ().GetPreambleType () >= WIFI_PREAMBLE_VHT_SU);
SnrPer snrPer = GetPhyHeaderSnrPer (WIFI_PPDU_FIELD_SIG_A, event);
NS_LOG_DEBUG ("SIG-A: SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per);
PhyFieldRxStatus status (GetRandomValue () > snrPer.per);
if (status.isSuccess)
{
NS_LOG_DEBUG ("Received SIG-A");
if (!IsAllConfigSupported (WIFI_PPDU_FIELD_SIG_A, event->GetPpdu ()))
{
status = PhyFieldRxStatus (false, UNSUPPORTED_SETTINGS, DROP);
}
status = ProcessSigA (event, status);
}
else
{
NS_LOG_DEBUG ("Drop packet because SIG-A reception failed");
status.reason = SIG_A_FAILURE;
status.actionIfFailure = DROP;
}
return status;
}
PhyEntity::PhyFieldRxStatus
VhtPhy::ProcessSigA (Ptr<Event> event, PhyFieldRxStatus status)
{
NS_LOG_FUNCTION (this << *event << status);
//TODO see if something should be done here once MU-MIMO is supported
return status; //nothing special for VHT
}
PhyEntity::PhyFieldRxStatus
VhtPhy::EndReceiveSigB (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
NS_ASSERT (event->GetPpdu ()->GetType () == WIFI_PPDU_TYPE_DL_MU);
SnrPer snrPer = GetPhyHeaderSnrPer (WIFI_PPDU_FIELD_SIG_B, event);
NS_LOG_DEBUG ("SIG-B: SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per);
PhyFieldRxStatus status (GetRandomValue () > snrPer.per);
if (status.isSuccess)
{
NS_LOG_DEBUG ("Received SIG-B");
if (!IsAllConfigSupported (WIFI_PPDU_FIELD_SIG_A, event->GetPpdu ()))
{
status = PhyFieldRxStatus (false, UNSUPPORTED_SETTINGS, DROP);
}
status = ProcessSigB (event, status);
}
else
{
NS_LOG_DEBUG ("Drop reception because SIG-B reception failed");
status.reason = SIG_B_FAILURE;
status.actionIfFailure = DROP;
}
return status;
}
PhyEntity::PhyFieldRxStatus
VhtPhy::ProcessSigB (Ptr<Event> event, PhyFieldRxStatus status)
{
NS_LOG_FUNCTION (this << *event << status);
//TODO see if something should be done here once MU-MIMO is supported
return status; //nothing special for VHT
}
bool
VhtPhy::IsAllConfigSupported (WifiPpduField field, Ptr<const WifiPpdu> ppdu) const
{
if (ppdu->GetType () == WIFI_PPDU_TYPE_DL_MU && field == WIFI_PPDU_FIELD_SIG_A)
{
return IsChannelWidthSupported (ppdu); //perform the full check after SIG-B
}
return HtPhy::IsAllConfigSupported (field, ppdu);
}
void
VhtPhy::InitializeModes (void)
{

View File

@@ -171,6 +171,50 @@ protected:
WifiMode GetHtSigMode (void) const override;
Time GetHtSigDuration (void) const override;
virtual uint8_t GetNumberBccEncoders (WifiTxVector txVector) const override;
virtual PhyFieldRxStatus DoEndReceiveField (WifiPpduField field, Ptr<Event> event) override;
virtual bool IsAllConfigSupported (WifiPpduField field, Ptr<const WifiPpdu> ppdu) const override;
/**
* End receiving the SIG-A, perform VHT-specific actions, and
* provide the status of the reception.
*
* Child classes can perform amendment-specific actions by specializing
* \see ProcessSigA.
*
* \param event the event holding incoming PPDU's information
* \return status of the reception of the SIG-A
*/
PhyFieldRxStatus EndReceiveSigA (Ptr<Event> event);
/**
* End receiving the SIG-B, perform VHT-specific actions, and
* provide the status of the reception.
*
* Child classes can perform amendment-specific actions by specializing
* \see ProcessSigB.
*
* \param event the event holding incoming PPDU's information
* \return status of the reception of the SIG-B
*/
PhyFieldRxStatus EndReceiveSigB (Ptr<Event> event);
/**
* Process SIG-A, perform amendment-specific actions, and
* provide an updated status of the reception.
*
* \param event the event holding incoming PPDU's information
* \param status the status of the reception of the correctly received SIG-A after the configuration support check
* \return the updated status of the reception of the SIG-A
*/
virtual PhyFieldRxStatus ProcessSigA (Ptr<Event> event, PhyFieldRxStatus status);
/**
* Process SIG-B, perform amendment-specific actions, and
* provide an updated status of the reception.
*
* \param event the event holding incoming PPDU's information
* \param status the status of the reception of the correctly received SIG-B after the configuration support check
* \return the updated status of the reception of the SIG-B
*/
virtual PhyFieldRxStatus ProcessSigB (Ptr<Event> event, PhyFieldRxStatus status);
private:
// Inherited

View File

@@ -1012,6 +1012,7 @@ WifiPhy::AddPhyEntity (WifiModulationClass modulation, Ptr<PhyEntity> phyEntity)
NS_LOG_FUNCTION (this << modulation);
NS_ABORT_MSG_IF (m_staticPhyEntities.find (modulation) == m_staticPhyEntities.end (), "Cannot add an unimplemented PHY to supported list. Update the former first.");
NS_ASSERT_MSG (m_phyEntities.find (modulation) == m_phyEntities.end (), "The PHY entity has already been added. The setting should only be done once per modulation class");
phyEntity->SetOwner (this);
m_phyEntities[modulation] = phyEntity;
}

View File

@@ -22,7 +22,6 @@
#ifndef WIFI_PHY_H
#define WIFI_PHY_H
#include "ns3/event-id.h"
#include "ns3/error-model.h"
#include "wifi-standards.h"
#include "interference-helper.h"
@@ -79,6 +78,7 @@ struct RxSignalInfo
class WifiPhy : public Object
{
public:
friend class PhyEntity;
/**
* \brief Get the type ID.
* \return the object TypeId
@@ -1187,7 +1187,7 @@ protected:
* \param channelWidth the channel width in MHz used for RSSI measurement
*/
void SwitchMaybeToCcaBusy (uint16_t channelWidth);
public: //TODO find a better way (robust enough for OfdmaSpectrumWifiPhy overload)
/**
* Return the STA ID that has been assigned to the station this PHY belongs to.
* This is typically called for MU PPDUs, in order to pick the correct PSDU.
@@ -1196,7 +1196,7 @@ protected:
* \return the STA ID
*/
virtual uint16_t GetStaId (const Ptr<const WifiPpdu> ppdu) const;
protected:
/**
* Return the channel width used to measure the RSSI.
* This corresponds to the primary channel unless it corresponds to the