wifi: Add preamble and payload handling in PhyEntity
Tx path will be refactored in subsequent commits. Please note that there are 7 crashing wifi test suites. They're solved in the next commit.
This commit is contained in:
@@ -26,11 +26,13 @@
|
||||
#include "he-configuration.h"
|
||||
#include "wifi-net-device.h"
|
||||
#include "sta-wifi-mac.h"
|
||||
#include "ap-wifi-mac.h"
|
||||
#include "wifi-utils.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/assert.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -245,7 +247,7 @@ HePhy::GetSigBDuration (WifiTxVector txVector) const
|
||||
}
|
||||
|
||||
uint16_t
|
||||
HePhy::ConvertHeTbPpduDurationToLSigLength (Time ppduDuration, WifiPhyBand band) const
|
||||
HePhy::ConvertHeTbPpduDurationToLSigLength (Time ppduDuration, WifiPhyBand band)
|
||||
{
|
||||
uint8_t sigExtension = 0;
|
||||
if (band == WIFI_PHY_BAND_2_4GHZ)
|
||||
@@ -258,11 +260,11 @@ HePhy::ConvertHeTbPpduDurationToLSigLength (Time ppduDuration, WifiPhyBand band)
|
||||
}
|
||||
|
||||
Time
|
||||
HePhy::ConvertLSigLengthToHeTbPpduDuration (uint16_t length, WifiTxVector txVector, WifiPhyBand band) const
|
||||
HePhy::ConvertLSigLengthToHeTbPpduDuration (uint16_t length, WifiTxVector txVector, WifiPhyBand band)
|
||||
{
|
||||
NS_ABORT_IF (txVector.GetPreambleType () != WIFI_PREAMBLE_HE_TB);
|
||||
Time tSymbol = NanoSeconds (12800 + txVector.GetGuardInterval ());
|
||||
Time preambleDuration = CalculatePhyPreambleAndHeaderDuration (txVector);
|
||||
Time preambleDuration = WifiPhy::GetStaticPhyEntity (WIFI_MOD_CLASS_HE)->CalculatePhyPreambleAndHeaderDuration (txVector); //this is quite convoluted but only way of keeping the method static
|
||||
uint8_t sigExtension = 0;
|
||||
if (band == WIFI_PHY_BAND_2_4GHZ)
|
||||
{
|
||||
@@ -307,6 +309,144 @@ HePhy::BuildPpdu (const WifiConstPsduMap & psdus, WifiTxVector txVector,
|
||||
return Create<HePpdu> (psdus, txVector, ppduDuration, band, uid);
|
||||
}
|
||||
|
||||
void
|
||||
HePhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxPowersW,
|
||||
Time rxDuration, TxPsdFlag psdFlag)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << ppdu << rxDuration << psdFlag);
|
||||
WifiTxVector txVector = ppdu->GetTxVector ();
|
||||
if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
|
||||
&& psdFlag == PSD_HE_TB_OFDMA_PORTION)
|
||||
{
|
||||
if (m_currentHeTbPpduUid == ppdu->GetUid ()
|
||||
&& GetCurrentEvent () != 0)
|
||||
{
|
||||
//AP or STA has already received non-OFDMA part, switch to OFDMA part, and schedule reception of payload (will be canceled for STAs by StartPayload)
|
||||
bool ofdmaStarted = !m_beginOfdmaPayloadRxEvents.empty ();
|
||||
NS_LOG_INFO ("Switch to OFDMA part (already started? " << (ofdmaStarted ? "Y" : "N") << ") " <<
|
||||
"and schedule OFDMA payload reception in " << GetDuration (WIFI_PPDU_FIELD_TRAINING, txVector).As (Time::NS));
|
||||
Ptr<Event> event = CreateInterferenceEvent (ppdu, txVector, rxDuration, rxPowersW, !ofdmaStarted);
|
||||
uint16_t staId = GetStaId (ppdu);
|
||||
NS_ASSERT (m_beginOfdmaPayloadRxEvents.find (staId) == m_beginOfdmaPayloadRxEvents.end ());
|
||||
m_beginOfdmaPayloadRxEvents[staId] = Simulator::Schedule (GetDuration (WIFI_PPDU_FIELD_TRAINING, txVector),
|
||||
&HePhy::StartReceiveOfdmaPayload, this, event);
|
||||
}
|
||||
else
|
||||
{
|
||||
//PHY receives the OFDMA payload while having dropped the preamble
|
||||
NS_LOG_INFO ("Consider OFDMA part of the HE TB PPDU as interference since device dropped the preamble");
|
||||
CreateInterferenceEvent (ppdu, txVector, rxDuration, rxPowersW);
|
||||
//the OFDMA part of the HE TB PPDUs will be noise _after_ the completion of the current event
|
||||
ErasePreambleEvent (ppdu, rxDuration);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PhyEntity::StartReceivePreamble (ppdu, rxPowersW, rxDuration, psdFlag);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HePhy::CancelAllEvents (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents)
|
||||
{
|
||||
beginOfdmaPayloadRxEvent.second.Cancel ();
|
||||
}
|
||||
m_beginOfdmaPayloadRxEvents.clear ();
|
||||
PhyEntity::CancelAllEvents ();
|
||||
}
|
||||
|
||||
void
|
||||
HePhy::DoAbortCurrentReception (WifiPhyRxfailureReason reason)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << reason);
|
||||
if (reason != OBSS_PD_CCA_RESET)
|
||||
{
|
||||
for (auto & endMpduEvent : m_endOfMpduEvents)
|
||||
{
|
||||
endMpduEvent.Cancel ();
|
||||
}
|
||||
m_endOfMpduEvents.clear ();
|
||||
}
|
||||
else
|
||||
{
|
||||
PhyEntity::DoAbortCurrentReception (reason);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HePhy::DoResetReceive (Ptr<Event> event)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *event);
|
||||
if (event->GetPpdu ()->GetType () != WIFI_PPDU_TYPE_UL_MU)
|
||||
{
|
||||
NS_ASSERT (event->GetEndTime () == Simulator::Now ());
|
||||
}
|
||||
for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents)
|
||||
{
|
||||
beginOfdmaPayloadRxEvent.second.Cancel ();
|
||||
}
|
||||
m_beginOfdmaPayloadRxEvents.clear ();
|
||||
}
|
||||
|
||||
Ptr<Event>
|
||||
HePhy::DoGetEvent (Ptr<const WifiPpdu> ppdu, RxPowerWattPerChannelBand rxPowersW)
|
||||
{
|
||||
Ptr<Event> event;
|
||||
//We store all incoming preamble events, and a decision is made at the end of the preamble detection window.
|
||||
//If a preamble is received after the preamble detection window, it is stored anyway because this is needed for HE TB PPDUs in
|
||||
//order to properly update the received power in InterferenceHelper. The map is cleaned anyway at the end of the current reception.
|
||||
if (ppdu->GetType () == WIFI_PPDU_TYPE_UL_MU)
|
||||
{
|
||||
auto uidPreamblePair = std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ());
|
||||
WifiTxVector txVector = ppdu->GetTxVector ();
|
||||
Time rxDuration = CalculateNonOfdmaDurationForHeTb (txVector); //the OFDMA part of the transmission will be added later on
|
||||
const auto & currentPreambleEvents = GetCurrentPreambleEvents ();
|
||||
auto it = currentPreambleEvents.find (uidPreamblePair);
|
||||
if (it != currentPreambleEvents.end ())
|
||||
{
|
||||
NS_LOG_DEBUG ("Received another HE TB PPDU for UID " << ppdu->GetUid () << " from STA-ID " << ppdu->GetStaId () << " and BSS color " << +txVector.GetBssColor ());
|
||||
event = it->second;
|
||||
if (Simulator::Now () - event->GetStartTime () > NanoSeconds (400))
|
||||
{
|
||||
//Section 27.3.14.3 from 802.11ax Draft 4.0: Pre-correction accuracy requirements.
|
||||
//A STA that transmits an HE TB PPDU, non-HT PPDU, or non-HT duplicate PPDU in response to a triggering PPDU
|
||||
//shall ensure that the transmission start time of the HE TB PPDU, non-HT PPDU, or non-HT duplicate PPDU is
|
||||
//within ±0.4 µs + 16 µs from the end, at the STA’s antenna connector, of the last OFDM symbol of the triggering
|
||||
//PPDU (if it contains no PE field) or of the PE field of the triggering PPDU (if the PE field is present).
|
||||
//As a result, if an HE TB PPDU arrives later than 0.4 µs, it is added as an interference but PPDU is dropped.
|
||||
event = CreateInterferenceEvent (ppdu, txVector, rxDuration, rxPowersW);
|
||||
NS_LOG_DEBUG ("Drop packet because not received within the 400ns window");
|
||||
m_wifiPhy->NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), HE_TB_PPDU_TOO_LATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Update received power of the event associated to that UL MU transmission
|
||||
UpdateInterferenceEvent (event, rxPowersW);
|
||||
}
|
||||
if ((GetCurrentEvent () != 0) && (GetCurrentEvent ()->GetPpdu ()->GetUid () != ppdu->GetUid ()))
|
||||
{
|
||||
NS_LOG_DEBUG ("Drop packet because already receiving another HE TB PPDU");
|
||||
m_wifiPhy->NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), RXING);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Received a new HE TB PPDU for UID " << ppdu->GetUid () << " from STA-ID " << ppdu->GetStaId () << " and BSS color " << +txVector.GetBssColor ());
|
||||
event = CreateInterferenceEvent (ppdu, txVector, rxDuration, rxPowersW);
|
||||
AddPreambleEvent (event);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
event = PhyEntity::DoGetEvent (ppdu, rxPowersW);
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
Ptr<const WifiPsdu>
|
||||
HePhy::GetAddressedPsduInPpdu (Ptr<const WifiPpdu> ppdu) const
|
||||
{
|
||||
@@ -340,8 +480,23 @@ HePhy::GetBssColor (void) const
|
||||
uint16_t
|
||||
HePhy::GetStaId (const Ptr<const WifiPpdu> ppdu) const
|
||||
{
|
||||
//TODO Move HE-specific logic here
|
||||
return m_wifiPhy->GetStaId (ppdu);
|
||||
if (ppdu->GetType () == WIFI_PPDU_TYPE_UL_MU)
|
||||
{
|
||||
return ppdu->GetStaId ();
|
||||
}
|
||||
else if (ppdu->GetType () == WIFI_PPDU_TYPE_DL_MU)
|
||||
{
|
||||
Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice> (m_wifiPhy->GetDevice ());
|
||||
if (device)
|
||||
{
|
||||
Ptr<StaWifiMac> mac = DynamicCast<StaWifiMac> (device->GetMac ());
|
||||
if (mac && mac->IsAssociated ())
|
||||
{
|
||||
return mac->GetAssociationId ();
|
||||
}
|
||||
}
|
||||
}
|
||||
return PhyEntity::GetStaId (ppdu);
|
||||
}
|
||||
|
||||
PhyEntity::PhyFieldRxStatus
|
||||
@@ -434,6 +589,159 @@ HePhy::IsConfigSupported (Ptr<const WifiPpdu> ppdu) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HePhy::DoStartReceivePayload (Ptr<Event> event)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *event);
|
||||
WifiTxVector txVector = event->GetTxVector ();
|
||||
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
|
||||
if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB)
|
||||
{
|
||||
Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice> (m_wifiPhy->GetDevice ());
|
||||
bool isAp = device != 0 && (DynamicCast<ApWifiMac> (device->GetMac ()) != 0);
|
||||
if (!isAp)
|
||||
{
|
||||
NS_LOG_DEBUG ("Ignore HE TB PPDU payload received by STA but keep state in Rx");
|
||||
m_endRxPayloadEvents.push_back (Simulator::Schedule (ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector),
|
||||
&PhyEntity::ResetReceive, this, event));
|
||||
//Cancel all scheduled events for OFDMA payload reception
|
||||
NS_ASSERT (!m_beginOfdmaPayloadRxEvents.empty () && m_beginOfdmaPayloadRxEvents.begin ()->second.IsRunning ());
|
||||
for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents)
|
||||
{
|
||||
beginOfdmaPayloadRxEvent.second.Cancel ();
|
||||
}
|
||||
m_beginOfdmaPayloadRxEvents.clear ();
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Receiving PSDU in HE TB PPDU");
|
||||
uint16_t staId = GetStaId (ppdu);
|
||||
m_signalNoiseMap.insert ({std::make_pair (ppdu->GetUid (), staId), SignalNoiseDbm ()});
|
||||
m_statusPerMpduMap.insert ({std::make_pair (ppdu->GetUid (), staId), std::vector<bool> ()});
|
||||
if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB)
|
||||
{
|
||||
//for HE TB PPDUs, ScheduleEndOfMpdus and EndReceive are scheduled by StartReceiveOfdmaPayload
|
||||
NS_ASSERT (isAp);
|
||||
NS_ASSERT (!m_beginOfdmaPayloadRxEvents.empty ());
|
||||
for (auto & beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents)
|
||||
{
|
||||
NS_ASSERT (beginOfdmaPayloadRxEvent.second.IsRunning ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PhyEntity::DoStartReceivePayload (event);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HePhy::DoEndReceivePayload (Ptr<const WifiPpdu> ppdu)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << ppdu);
|
||||
if (ppdu->GetType () == WIFI_PPDU_TYPE_UL_MU)
|
||||
{
|
||||
for (auto it = m_endRxPayloadEvents.begin (); it != m_endRxPayloadEvents.end (); )
|
||||
{
|
||||
if (it->IsExpired ())
|
||||
{
|
||||
it = m_endRxPayloadEvents.erase (it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
if (m_endRxPayloadEvents.empty ())
|
||||
{
|
||||
//We've got the last PPDU of the UL-OFDMA transmission
|
||||
NotifyInterferenceRxEndAndClear (true); //reset WifiPhy
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERT (m_wifiPhy->GetLastRxEndTime () == Simulator::Now ());
|
||||
PhyEntity::DoEndReceivePayload (ppdu);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HePhy::StartReceiveOfdmaPayload (Ptr<Event> event)
|
||||
{
|
||||
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
|
||||
RxPowerWattPerChannelBand rxPowersW = event->GetRxPowerWPerBand ();
|
||||
//The total RX power corresponds to the maximum over all the bands
|
||||
auto it = std::max_element (rxPowersW.begin (), rxPowersW.end (),
|
||||
[] (const std::pair<WifiSpectrumBand, double> &p1, const std::pair<WifiSpectrumBand, double> &p2) {
|
||||
return p1.second < p2.second;
|
||||
});
|
||||
NS_LOG_FUNCTION (this << *event << it->second);
|
||||
NS_ASSERT (GetCurrentEvent () != 0);
|
||||
auto itEvent = m_beginOfdmaPayloadRxEvents.find (GetStaId (ppdu));
|
||||
/**
|
||||
* m_beginOfdmaPayloadRxEvents should still be running only for APs, since canceled in StartReceivePayload for STAs.
|
||||
* This is because SpectrumWifiPhy does not have access to the device type and thus blindly schedules things, letting
|
||||
* the parent WifiPhy class take into account device type.
|
||||
*/
|
||||
NS_ASSERT (itEvent != m_beginOfdmaPayloadRxEvents.end () && itEvent->second.IsExpired ());
|
||||
m_beginOfdmaPayloadRxEvents.erase (itEvent);
|
||||
|
||||
Time payloadDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (ppdu->GetTxVector ());
|
||||
Ptr<const WifiPsdu> psdu = GetAddressedPsduInPpdu (ppdu);
|
||||
ScheduleEndOfMpdus (event);
|
||||
m_endRxPayloadEvents.push_back (Simulator::Schedule (payloadDuration, &PhyEntity::EndReceivePayload, this, event));
|
||||
m_signalNoiseMap.insert ({std::make_pair (ppdu->GetUid (), ppdu->GetStaId ()), SignalNoiseDbm ()});
|
||||
m_statusPerMpduMap.insert ({std::make_pair (ppdu->GetUid (), ppdu->GetStaId ()), std::vector<bool> ()});
|
||||
}
|
||||
|
||||
std::pair<uint16_t, WifiSpectrumBand>
|
||||
HePhy::GetChannelWidthAndBand (WifiTxVector txVector, uint16_t staId) const
|
||||
{
|
||||
if (txVector.IsMu ())
|
||||
{
|
||||
return std::make_pair (HeRu::GetBandwidth (txVector.GetRu (staId).ruType),
|
||||
GetRuBand (txVector, staId));
|
||||
}
|
||||
else
|
||||
{
|
||||
return PhyEntity::GetChannelWidthAndBand (txVector, staId);
|
||||
}
|
||||
}
|
||||
|
||||
WifiSpectrumBand
|
||||
HePhy::GetRuBand (WifiTxVector txVector, uint16_t staId) const
|
||||
{
|
||||
NS_ASSERT (txVector.IsMu ());
|
||||
WifiSpectrumBand band;
|
||||
HeRu::RuSpec ru = txVector.GetRu (staId);
|
||||
uint16_t channelWidth = txVector.GetChannelWidth ();
|
||||
NS_ASSERT (channelWidth <= m_wifiPhy->GetChannelWidth ());
|
||||
HeRu::SubcarrierGroup group = HeRu::GetSubcarrierGroup (channelWidth, ru.ruType, ru.index);
|
||||
HeRu::SubcarrierRange range = std::make_pair (group.front ().first, group.back ().second);
|
||||
band = m_wifiPhy->ConvertHeRuSubcarriers (channelWidth, range);
|
||||
return band;
|
||||
}
|
||||
|
||||
WifiSpectrumBand
|
||||
HePhy::GetNonOfdmaBand (WifiTxVector txVector, uint16_t staId) const
|
||||
{
|
||||
NS_ASSERT (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB);
|
||||
uint16_t channelWidth = txVector.GetChannelWidth ();
|
||||
NS_ASSERT (channelWidth <= m_wifiPhy->GetChannelWidth ());
|
||||
|
||||
HeRu::RuSpec ru = txVector.GetRu (staId);
|
||||
uint16_t ruWidth = HeRu::GetBandwidth (ru.ruType);
|
||||
uint16_t nonOfdmaWidth = ruWidth < 20 ? 20 : ruWidth;
|
||||
|
||||
// Find the RU that encompasses the non-OFDMA part of the HE TB PPDU for the STA-ID
|
||||
HeRu::RuSpec nonOfdmaRu = HeRu::FindOverlappingRu (channelWidth, ru, HeRu::GetRuType (nonOfdmaWidth));
|
||||
|
||||
HeRu::SubcarrierGroup groupPreamble = HeRu::GetSubcarrierGroup (channelWidth, nonOfdmaRu.ruType, nonOfdmaRu.index);
|
||||
HeRu::SubcarrierRange range = std::make_pair (groupPreamble.front ().first, groupPreamble.back ().second);
|
||||
return m_wifiPhy->ConvertHeRuSubcarriers (channelWidth, range);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
HePhy::GetCurrentHeTbPpduUid (void) const
|
||||
{
|
||||
|
||||
@@ -74,28 +74,23 @@ public:
|
||||
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;
|
||||
void StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxPowersW,
|
||||
Time rxDuration, TxPsdFlag psdFlag) override;
|
||||
void CancelAllEvents (void) override;
|
||||
virtual uint16_t GetStaId (const 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
|
||||
* \param band the frequency band being used
|
||||
*
|
||||
* \return the L-SIG length value corresponding to that HE TB PPDU duration.
|
||||
*/
|
||||
uint16_t ConvertHeTbPpduDurationToLSigLength (Time ppduDuration, WifiPhyBand band) const;
|
||||
static uint16_t ConvertHeTbPpduDurationToLSigLength (Time ppduDuration, WifiPhyBand band);
|
||||
/**
|
||||
* \param length the L-SIG length value
|
||||
* \param txVector the TXVECTOR used for the transmission of this HE TB PPDU
|
||||
@@ -103,7 +98,7 @@ public:
|
||||
*
|
||||
* \return the duration of the HE TB PPDU corresponding to that L-SIG length value.
|
||||
*/
|
||||
Time ConvertLSigLengthToHeTbPpduDuration (uint16_t length, WifiTxVector txVector, WifiPhyBand band) const;
|
||||
static Time ConvertLSigLengthToHeTbPpduDuration (uint16_t length, WifiTxVector txVector, WifiPhyBand band);
|
||||
/**
|
||||
* \param txVector the transmission parameters used for the HE TB PPDU
|
||||
*
|
||||
@@ -111,6 +106,25 @@ public:
|
||||
*/
|
||||
Time CalculateNonOfdmaDurationForHeTb (WifiTxVector txVector) const;
|
||||
|
||||
/**
|
||||
* Get the RU band used to transmit a PSDU to a given STA in a HE MU PPDU
|
||||
*
|
||||
* \param txVector the TXVECTOR used for the transmission
|
||||
* \param staId the STA-ID of the recipient
|
||||
*
|
||||
* \return the RU band used to transmit a PSDU to a given STA in a HE MU PPDU
|
||||
*/
|
||||
WifiSpectrumBand GetRuBand (WifiTxVector txVector, uint16_t staId) const;
|
||||
/**
|
||||
* Get the band used to transmit the non-OFDMA part of an HE TB PPDU.
|
||||
*
|
||||
* \param txVector the TXVECTOR used for the transmission
|
||||
* \param staId the STA-ID of the station taking part of the UL MU
|
||||
*
|
||||
* \return the spectrum band used to transmit the non-OFDMA part of an HE TB PPDU
|
||||
*/
|
||||
WifiSpectrumBand GetNonOfdmaBand (WifiTxVector txVector, uint16_t staId) const;
|
||||
|
||||
/**
|
||||
* \return the UID of the HE TB PPDU being received
|
||||
*/
|
||||
@@ -206,10 +220,26 @@ protected:
|
||||
// Inherited
|
||||
PhyFieldRxStatus ProcessSigA (Ptr<Event> event, PhyFieldRxStatus status) override;
|
||||
PhyFieldRxStatus ProcessSigB (Ptr<Event> event, PhyFieldRxStatus status) override;
|
||||
Ptr<Event> DoGetEvent (Ptr<const WifiPpdu> ppdu, RxPowerWattPerChannelBand rxPowersW) override;
|
||||
virtual bool IsConfigSupported (Ptr<const WifiPpdu> ppdu) const override;
|
||||
virtual void DoStartReceivePayload (Ptr<Event> event) override;
|
||||
std::pair<uint16_t, WifiSpectrumBand> GetChannelWidthAndBand (WifiTxVector txVector, uint16_t staId) const override;
|
||||
void DoEndReceivePayload (Ptr<const WifiPpdu> ppdu) override;
|
||||
void DoResetReceive (Ptr<Event> event) override;
|
||||
void DoAbortCurrentReception (WifiPhyRxfailureReason reason) override;
|
||||
|
||||
/**
|
||||
* Start receiving the PSDU (i.e. the first symbol of the PSDU has arrived) of an UL-OFDMA transmission.
|
||||
* This function is called upon the RX event corresponding to the OFDMA part of the UL MU PPDU.
|
||||
*
|
||||
* \param event the event holding incoming OFDMA part of the PPDU's information
|
||||
*/
|
||||
void StartReceiveOfdmaPayload (Ptr<Event> event);
|
||||
|
||||
uint64_t m_currentHeTbPpduUid; //!< UID of the HE TB PPDU being received
|
||||
|
||||
std::map <uint16_t /* STA-ID */, EventId> m_beginOfdmaPayloadRxEvents; //!< the beginning of the OFDMA payload reception events (indexed by STA-ID)
|
||||
|
||||
private:
|
||||
// Inherited
|
||||
virtual void BuildModeList (void) override;
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
#include "wifi-phy.h"
|
||||
#include "wifi-psdu.h"
|
||||
#include "preamble-detection-model.h"
|
||||
#include "frame-capture-model.h"
|
||||
#include "wifi-utils.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/assert.h"
|
||||
@@ -68,7 +70,9 @@ std::ostream & operator << (std::ostream &os, const PhyEntity::PhyFieldRxStatus
|
||||
|
||||
PhyEntity::~PhyEntity ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_modeList.clear ();
|
||||
CancelAllEvents ();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -246,20 +250,12 @@ 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;
|
||||
}
|
||||
NS_ASSERT (m_wifiPhy->m_endPhyRxEvent.IsExpired ());
|
||||
NS_ABORT_MSG_IF (field == WIFI_PPDU_FIELD_PREAMBLE, "Use the StartReceivePreamble method for preamble reception");
|
||||
//Handle special cases of data reception
|
||||
if (field == WIFI_PPDU_FIELD_DATA)
|
||||
{
|
||||
//TODO improve this logic later on
|
||||
//Hand over to WifiPhy for data processing
|
||||
m_wifiPhy->StartReceivePayload (event);
|
||||
StartReceivePayload (event);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -304,10 +300,11 @@ PhyEntity::EndReceiveField (WifiPpduField field, Ptr<Event> event)
|
||||
//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
|
||||
//no break
|
||||
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));
|
||||
m_endRxPayloadEvents.push_back (Simulator::Schedule (GetRemainingDurationAfterField (ppdu, field),
|
||||
&PhyEntity::ResetReceive, this, event));
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Unknown action in case of failure");
|
||||
@@ -352,13 +349,423 @@ PhyEntity::DoEndReceiveField (WifiPpduField field, Ptr<Event> event)
|
||||
return PhyFieldRxStatus (false); //failed reception by default
|
||||
}
|
||||
|
||||
bool
|
||||
PhyEntity::DoStartReceivePreamble (Ptr<Event> event)
|
||||
void
|
||||
PhyEntity::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxPowersW,
|
||||
Time /* rxDuration */, TxPsdFlag /* psdFlag */)
|
||||
{
|
||||
//The total RX power corresponds to the maximum over all the bands
|
||||
auto it = std::max_element (rxPowersW.begin (), rxPowersW.end (),
|
||||
[] (const std::pair<WifiSpectrumBand, double> &p1, const std::pair<WifiSpectrumBand, double> &p2) {
|
||||
return p1.second < p2.second;
|
||||
});
|
||||
NS_LOG_FUNCTION (this << ppdu << it->second);
|
||||
WifiTxVector txVector = ppdu->GetTxVector ();
|
||||
Time rxDuration = ppdu->GetTxDuration (); //the actual duration of the PPDU should be considered
|
||||
|
||||
Ptr<Event> event = DoGetEvent (ppdu, rxPowersW);
|
||||
if (event == nullptr)
|
||||
{
|
||||
//PPDU should be simply considered as interference (once it has been accounted for in InterferenceHelper)
|
||||
return;
|
||||
}
|
||||
|
||||
Time endRx = Simulator::Now () + rxDuration;
|
||||
if (m_state->GetState () == WifiPhyState::OFF)
|
||||
{
|
||||
NS_LOG_DEBUG ("Cannot start RX because device is OFF");
|
||||
if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
|
||||
{
|
||||
m_wifiPhy->MaybeCcaBusyDuration (m_wifiPhy->GetMeasurementChannelWidth (nullptr));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ppdu->IsTruncatedTx ())
|
||||
{
|
||||
NS_LOG_DEBUG ("Packet reception stopped because transmitter has been switched off");
|
||||
if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
|
||||
{
|
||||
m_wifiPhy->MaybeCcaBusyDuration (m_wifiPhy->GetMeasurementChannelWidth (ppdu));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (m_state->GetState ())
|
||||
{
|
||||
case WifiPhyState::SWITCHING:
|
||||
NS_LOG_DEBUG ("Drop packet because of channel switching");
|
||||
/*
|
||||
* Packets received on the upcoming channel are added to the event list
|
||||
* during the switching state. This way the medium can be correctly sensed
|
||||
* when the device listens to the channel for the first time after the
|
||||
* switching e.g. after channel switching, the channel may be sensed as
|
||||
* busy due to other devices' transmissions started before the end of
|
||||
* the switching.
|
||||
*/
|
||||
DropPreambleEvent (ppdu, CHANNEL_SWITCHING, endRx, m_wifiPhy->GetMeasurementChannelWidth (ppdu));
|
||||
break;
|
||||
case WifiPhyState::RX:
|
||||
if (m_wifiPhy->m_frameCaptureModel != 0
|
||||
&& m_wifiPhy->m_frameCaptureModel->IsInCaptureWindow (m_wifiPhy->m_timeLastPreambleDetected)
|
||||
&& m_wifiPhy->m_frameCaptureModel->CaptureNewFrame (m_wifiPhy->m_currentEvent, event))
|
||||
{
|
||||
AbortCurrentReception (FRAME_CAPTURE_PACKET_SWITCH);
|
||||
NS_LOG_DEBUG ("Switch to new packet");
|
||||
StartPreambleDetectionPeriod (event);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Drop packet because already in Rx");
|
||||
DropPreambleEvent (ppdu, RXING, endRx, m_wifiPhy->GetMeasurementChannelWidth (ppdu));
|
||||
if (m_wifiPhy->m_currentEvent == 0)
|
||||
{
|
||||
/*
|
||||
* We are here because the non-legacy PHY header has not been successfully received.
|
||||
* The PHY is kept in RX state for the duration of the PPDU, but EndReceive function is
|
||||
* not called when the reception of the PPDU is finished, which is responsible to clear
|
||||
* m_currentPreambleEvents. As a result, m_currentPreambleEvents should be cleared here.
|
||||
*/
|
||||
m_wifiPhy->m_currentPreambleEvents.clear ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WifiPhyState::TX:
|
||||
NS_LOG_DEBUG ("Drop packet because already in Tx");
|
||||
DropPreambleEvent (ppdu, TXING, endRx, m_wifiPhy->GetMeasurementChannelWidth (ppdu));
|
||||
break;
|
||||
case WifiPhyState::CCA_BUSY:
|
||||
if (m_wifiPhy->m_currentEvent != 0)
|
||||
{
|
||||
if (m_wifiPhy->m_frameCaptureModel != 0
|
||||
&& m_wifiPhy->m_frameCaptureModel->IsInCaptureWindow (m_wifiPhy->m_timeLastPreambleDetected)
|
||||
&& m_wifiPhy->m_frameCaptureModel->CaptureNewFrame (m_wifiPhy->m_currentEvent, event))
|
||||
{
|
||||
AbortCurrentReception (FRAME_CAPTURE_PACKET_SWITCH);
|
||||
NS_LOG_DEBUG ("Switch to new packet");
|
||||
StartPreambleDetectionPeriod (event);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Drop packet because already decoding preamble");
|
||||
DropPreambleEvent (ppdu, BUSY_DECODING_PREAMBLE, endRx, m_wifiPhy->GetMeasurementChannelWidth (ppdu));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StartPreambleDetectionPeriod (event);
|
||||
}
|
||||
break;
|
||||
case WifiPhyState::IDLE:
|
||||
NS_ASSERT (m_wifiPhy->m_currentEvent == 0);
|
||||
StartPreambleDetectionPeriod (event);
|
||||
break;
|
||||
case WifiPhyState::SLEEP:
|
||||
NS_LOG_DEBUG ("Drop packet because in sleep mode");
|
||||
DropPreambleEvent (ppdu, SLEEPING, endRx, m_wifiPhy->GetMeasurementChannelWidth (nullptr));
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Invalid WifiPhy state.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::DropPreambleEvent (Ptr<const WifiPpdu> ppdu, WifiPhyRxfailureReason reason, Time endRx, uint16_t measurementChannelWidth)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << ppdu << reason << endRx << measurementChannelWidth);
|
||||
m_wifiPhy->NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), reason);
|
||||
auto it = m_wifiPhy->m_currentPreambleEvents.find (std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()));
|
||||
if (it != m_wifiPhy->m_currentPreambleEvents.end ())
|
||||
{
|
||||
m_wifiPhy->m_currentPreambleEvents.erase (it);
|
||||
}
|
||||
if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
|
||||
{
|
||||
//that PPDU will be noise _after_ the end of the current event.
|
||||
m_wifiPhy->MaybeCcaBusyDuration (measurementChannelWidth);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::ErasePreambleEvent (Ptr<const WifiPpdu> ppdu, Time rxDuration)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << ppdu << rxDuration);
|
||||
auto it = m_wifiPhy->m_currentPreambleEvents.find (std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()));
|
||||
if (it != m_wifiPhy->m_currentPreambleEvents.end ())
|
||||
{
|
||||
m_wifiPhy->m_currentPreambleEvents.erase (it);
|
||||
}
|
||||
if (m_wifiPhy->m_currentPreambleEvents.empty ())
|
||||
{
|
||||
m_wifiPhy->Reset ();
|
||||
}
|
||||
|
||||
if (rxDuration > m_state->GetDelayUntilIdle ())
|
||||
{
|
||||
//this PPDU will be noise _after_ the completion of the current event
|
||||
m_wifiPhy->SwitchMaybeToCcaBusy (m_wifiPhy->GetMeasurementChannelWidth (ppdu));
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
PhyEntity::GetStaId (const Ptr<const WifiPpdu> /* ppdu */) const
|
||||
{
|
||||
return SU_STA_ID;
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::StartReceivePayload (Ptr<Event> event)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *event);
|
||||
//TODO handle special cases in WifiPhy::StartReceivePreamble
|
||||
StartPreambleDetectionPeriod (event);
|
||||
return true;
|
||||
NS_ASSERT (m_wifiPhy->m_endPhyRxEvent.IsExpired ());
|
||||
WifiTxVector txVector = event->GetTxVector ();
|
||||
Time payloadDuration = event->GetPpdu ()->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
|
||||
|
||||
//TODO: Add method in WifiPhy to clear all other PHYs (since this one is starting Rx)
|
||||
m_state->SwitchToRx (payloadDuration);
|
||||
m_wifiPhy->m_phyRxPayloadBeginTrace (txVector, payloadDuration); //this callback (equivalent to PHY-RXSTART primitive) is triggered only if headers have been correctly decoded and that the mode within is supported
|
||||
|
||||
DoStartReceivePayload (event);
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::DoStartReceivePayload (Ptr<Event> event)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *event);
|
||||
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
|
||||
NS_LOG_DEBUG ("Receiving PSDU");
|
||||
uint16_t staId = GetStaId (ppdu);
|
||||
m_signalNoiseMap.insert ({std::make_pair (ppdu->GetUid (), staId), SignalNoiseDbm ()});
|
||||
m_statusPerMpduMap.insert ({std::make_pair (ppdu->GetUid (), staId), std::vector<bool> ()});
|
||||
ScheduleEndOfMpdus (event);
|
||||
m_endRxPayloadEvents.push_back (Simulator::Schedule (ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (event->GetTxVector ()),
|
||||
&PhyEntity::EndReceivePayload, this, event));
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::ScheduleEndOfMpdus (Ptr<Event> event)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *event);
|
||||
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
|
||||
Ptr<const WifiPsdu> psdu = GetAddressedPsduInPpdu (ppdu);
|
||||
WifiTxVector txVector = event->GetTxVector ();
|
||||
uint16_t staId = GetStaId (ppdu);
|
||||
Time endOfMpduDuration = NanoSeconds (0);
|
||||
Time relativeStart = NanoSeconds (0);
|
||||
Time psduDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
|
||||
Time remainingAmpduDuration = psduDuration;
|
||||
size_t nMpdus = psdu->GetNMpdus ();
|
||||
MpduType mpduType = (nMpdus > 1) ? FIRST_MPDU_IN_AGGREGATE : (psdu->IsSingle () ? SINGLE_MPDU : NORMAL_MPDU);
|
||||
uint32_t totalAmpduSize = 0;
|
||||
double totalAmpduNumSymbols = 0.0;
|
||||
auto mpdu = psdu->begin ();
|
||||
for (size_t i = 0; i < nMpdus && mpdu != psdu->end (); ++mpdu)
|
||||
{
|
||||
uint32_t size = (mpduType == NORMAL_MPDU) ? psdu->GetSize () : psdu->GetAmpduSubframeSize (i);
|
||||
Time mpduDuration = m_wifiPhy->GetPayloadDuration (size, txVector,
|
||||
m_wifiPhy->GetPhyBand (), mpduType, true, totalAmpduSize,
|
||||
totalAmpduNumSymbols, staId);
|
||||
|
||||
remainingAmpduDuration -= mpduDuration;
|
||||
if (i == (nMpdus - 1) && !remainingAmpduDuration.IsZero ()) //no more MPDUs coming
|
||||
{
|
||||
if (remainingAmpduDuration < NanoSeconds (txVector.GetGuardInterval ())) //enables to ignore padding
|
||||
{
|
||||
mpduDuration += remainingAmpduDuration; //apply a correction just in case rounding had induced slight shift
|
||||
}
|
||||
}
|
||||
|
||||
endOfMpduDuration += mpduDuration;
|
||||
NS_LOG_INFO ("Schedule end of MPDU #" << i << " in " << endOfMpduDuration.As (Time::NS) <<
|
||||
" (relativeStart=" << relativeStart.As (Time::NS) << ", mpduDuration=" << mpduDuration.As (Time::NS) <<
|
||||
", remainingAmdpuDuration=" << remainingAmpduDuration.As (Time::NS) << ")");
|
||||
m_endOfMpduEvents.push_back (Simulator::Schedule (endOfMpduDuration, &PhyEntity::EndOfMpdu, this, event, Create<WifiPsdu> (*mpdu, false), i, relativeStart, mpduDuration));
|
||||
|
||||
//Prepare next iteration
|
||||
++i;
|
||||
relativeStart += mpduDuration;
|
||||
mpduType = (i == (nMpdus - 1)) ? LAST_MPDU_IN_AGGREGATE : MIDDLE_MPDU_IN_AGGREGATE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::EndOfMpdu (Ptr<Event> event, Ptr<const WifiPsdu> psdu, size_t mpduIndex, Time relativeStart, Time mpduDuration)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *event << mpduIndex << relativeStart << mpduDuration);
|
||||
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
|
||||
WifiTxVector txVector = event->GetTxVector ();
|
||||
uint16_t staId = GetStaId (ppdu);
|
||||
const auto & channelWidthAndBand = GetChannelWidthAndBand (event->GetTxVector (), staId);
|
||||
double snr = m_wifiPhy->m_interference.CalculateSnr (event, channelWidthAndBand.first, txVector.GetNss (staId), channelWidthAndBand.second);
|
||||
|
||||
std::pair<bool, SignalNoiseDbm> rxInfo = GetReceptionStatus (psdu, event, staId, relativeStart, mpduDuration);
|
||||
NS_LOG_DEBUG ("Extracted MPDU #" << mpduIndex << ": duration: " << mpduDuration.As (Time::NS) <<
|
||||
", correct reception: " << rxInfo.first << ", Signal/Noise: " << rxInfo.second.signal << "/" << rxInfo.second.noise << "dBm");
|
||||
|
||||
auto signalNoiseIt = m_signalNoiseMap.find (std::make_pair (ppdu->GetUid (), staId));
|
||||
NS_ASSERT (signalNoiseIt != m_signalNoiseMap.end ());
|
||||
signalNoiseIt->second = rxInfo.second;
|
||||
|
||||
RxSignalInfo rxSignalInfo;
|
||||
rxSignalInfo.snr = snr;
|
||||
rxSignalInfo.rssi = rxInfo.second.signal;
|
||||
|
||||
auto statusPerMpduIt = m_statusPerMpduMap.find (std::make_pair (ppdu->GetUid (), staId));
|
||||
NS_ASSERT (statusPerMpduIt != m_statusPerMpduMap.end ());
|
||||
statusPerMpduIt->second.push_back (rxInfo.first);
|
||||
|
||||
if (rxInfo.first && GetAddressedPsduInPpdu (ppdu)->GetNMpdus () > 1)
|
||||
{
|
||||
//only done for correct MPDU that is part of an A-MPDU
|
||||
m_state->ContinueRxNextMpdu (Copy (psdu), rxSignalInfo, txVector);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::EndReceivePayload (Ptr<Event> event)
|
||||
{
|
||||
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
|
||||
WifiTxVector txVector = event->GetTxVector ();
|
||||
Time psduDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
|
||||
NS_LOG_FUNCTION (this << *event << psduDuration);
|
||||
NS_ASSERT (event->GetEndTime () == Simulator::Now ());
|
||||
uint16_t staId = GetStaId (ppdu);
|
||||
const auto & channelWidthAndBand = GetChannelWidthAndBand (event->GetTxVector (), staId);
|
||||
double snr = m_wifiPhy->m_interference.CalculateSnr (event, channelWidthAndBand.first, txVector.GetNss (staId), channelWidthAndBand.second);
|
||||
|
||||
Ptr<const WifiPsdu> psdu = GetAddressedPsduInPpdu (ppdu);
|
||||
m_wifiPhy->NotifyRxEnd (psdu);
|
||||
|
||||
auto signalNoiseIt = m_signalNoiseMap.find (std::make_pair (ppdu->GetUid (), staId));
|
||||
NS_ASSERT (signalNoiseIt != m_signalNoiseMap.end ());
|
||||
auto statusPerMpduIt = m_statusPerMpduMap.find (std::make_pair (ppdu->GetUid (), staId));
|
||||
NS_ASSERT (statusPerMpduIt != m_statusPerMpduMap.end ());
|
||||
|
||||
if (std::count (statusPerMpduIt->second.begin (), statusPerMpduIt->second.end (), true))
|
||||
{
|
||||
//At least one MPDU has been successfully received
|
||||
m_wifiPhy->NotifyMonitorSniffRx (psdu, m_wifiPhy->GetFrequency (), txVector, signalNoiseIt->second, statusPerMpduIt->second, staId);
|
||||
RxSignalInfo rxSignalInfo;
|
||||
rxSignalInfo.snr = snr;
|
||||
rxSignalInfo.rssi = signalNoiseIt->second.signal; //same information for all MPDUs
|
||||
m_state->SwitchFromRxEndOk (Copy (psdu), rxSignalInfo, txVector, staId, statusPerMpduIt->second);
|
||||
m_wifiPhy->m_previouslyRxPpduUid = event->GetPpdu ()->GetUid (); //store UID only if reception is successful (because otherwise trigger won't be read by MAC layer)
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state->SwitchFromRxEndError (Copy (psdu), snr);
|
||||
}
|
||||
|
||||
DoEndReceivePayload (ppdu);
|
||||
m_wifiPhy->MaybeCcaBusyDuration (m_wifiPhy->GetMeasurementChannelWidth (ppdu));
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::DoEndReceivePayload (Ptr<const WifiPpdu> ppdu)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << ppdu);
|
||||
NS_ASSERT (m_wifiPhy->GetLastRxEndTime () == Simulator::Now ());
|
||||
NotifyInterferenceRxEndAndClear (false); //don't reset WifiPhy
|
||||
|
||||
m_wifiPhy->m_currentEvent = 0;
|
||||
m_wifiPhy->m_currentPreambleEvents.clear ();
|
||||
m_endRxPayloadEvents.clear ();
|
||||
}
|
||||
|
||||
std::pair<bool, SignalNoiseDbm>
|
||||
PhyEntity::GetReceptionStatus (Ptr<const WifiPsdu> psdu, Ptr<Event> event, uint16_t staId,
|
||||
Time relativeMpduStart, Time mpduDuration)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *psdu << *event << staId << relativeMpduStart << mpduDuration);
|
||||
const auto & channelWidthAndBand = GetChannelWidthAndBand (event->GetTxVector (), staId);
|
||||
SnrPer snrPer = m_wifiPhy->m_interference.CalculatePayloadSnrPer (event, channelWidthAndBand.first, channelWidthAndBand.second, staId,
|
||||
std::make_pair (relativeMpduStart, relativeMpduStart + mpduDuration));
|
||||
|
||||
WifiMode mode = event->GetTxVector ().GetMode (staId);
|
||||
NS_LOG_DEBUG ("rate=" << (mode.GetDataRate (event->GetTxVector (), staId)) <<
|
||||
", SNR(dB)=" << RatioToDb (snrPer.snr) << ", PER=" << snrPer.per << ", size=" << psdu->GetSize () <<
|
||||
", relativeStart = " << relativeMpduStart.As (Time::NS) << ", duration = " << mpduDuration.As (Time::NS));
|
||||
|
||||
// There are two error checks: PER and receive error model check.
|
||||
// PER check models is typical for Wi-Fi and is based on signal modulation;
|
||||
// Receive error model is optional, if we have an error model and
|
||||
// it indicates that the packet is corrupt, drop the packet.
|
||||
SignalNoiseDbm signalNoise;
|
||||
signalNoise.signal = WToDbm (event->GetRxPowerW (channelWidthAndBand.second));
|
||||
signalNoise.noise = WToDbm (event->GetRxPowerW (channelWidthAndBand.second) / snrPer.snr);
|
||||
if (GetRandomValue () > snrPer.per
|
||||
&& !(m_wifiPhy->m_postReceptionErrorModel && m_wifiPhy->m_postReceptionErrorModel->IsCorrupt (psdu->GetPacket ()->Copy ())))
|
||||
{
|
||||
NS_LOG_DEBUG ("Reception succeeded: " << psdu);
|
||||
return std::make_pair (true, signalNoise);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Reception failed: " << psdu);
|
||||
return std::make_pair (false, signalNoise);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<uint16_t, WifiSpectrumBand>
|
||||
PhyEntity::GetChannelWidthAndBand (WifiTxVector txVector, uint16_t /* staId */) const
|
||||
{
|
||||
uint16_t channelWidth = std::min (m_wifiPhy->GetChannelWidth (), txVector.GetChannelWidth ());
|
||||
return std::make_pair (channelWidth, m_wifiPhy->GetBand (channelWidth));
|
||||
}
|
||||
|
||||
const std::map <std::pair<uint64_t, WifiPreamble>, Ptr<Event> > &
|
||||
PhyEntity::GetCurrentPreambleEvents (void) const
|
||||
{
|
||||
return m_wifiPhy->m_currentPreambleEvents;
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::AddPreambleEvent (Ptr<Event> event)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *event);
|
||||
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
|
||||
m_wifiPhy->m_currentPreambleEvents.insert ({std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()), event});
|
||||
}
|
||||
|
||||
Ptr<Event>
|
||||
PhyEntity::DoGetEvent (Ptr<const WifiPpdu> ppdu, RxPowerWattPerChannelBand rxPowersW)
|
||||
{
|
||||
Ptr<Event> event = CreateInterferenceEvent (ppdu, ppdu->GetTxVector (), ppdu->GetTxDuration (), rxPowersW);
|
||||
|
||||
//We store all incoming preamble events, and a decision is made at the end of the preamble detection window.
|
||||
auto uidPreamblePair = std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ());
|
||||
NS_ASSERT (m_wifiPhy->m_currentPreambleEvents.find (uidPreamblePair) == m_wifiPhy->m_currentPreambleEvents.end ());
|
||||
m_wifiPhy->m_currentPreambleEvents.insert ({uidPreamblePair, event});
|
||||
return event;
|
||||
}
|
||||
|
||||
Ptr<Event>
|
||||
PhyEntity::CreateInterferenceEvent (Ptr<const WifiPpdu> ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPower, bool isStartOfdmaRxing /* = false */)
|
||||
{
|
||||
return m_wifiPhy->m_interference.Add (ppdu, txVector, duration, rxPower, isStartOfdmaRxing);
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::UpdateInterferenceEvent (Ptr<Event> event, RxPowerWattPerChannelBand rxPower)
|
||||
{
|
||||
m_wifiPhy->m_interference.UpdateEvent (event, rxPower);
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::NotifyInterferenceRxEndAndClear (bool reset)
|
||||
{
|
||||
m_wifiPhy->m_interference.NotifyRxEnd (Simulator::Now ());
|
||||
m_signalNoiseMap.clear ();
|
||||
m_statusPerMpduMap.clear ();
|
||||
for (const auto & endOfMpduEvent : m_endOfMpduEvents)
|
||||
{
|
||||
NS_ASSERT (endOfMpduEvent.IsExpired ());
|
||||
}
|
||||
m_endOfMpduEvents.clear ();
|
||||
if (reset)
|
||||
{
|
||||
m_wifiPhy->Reset ();
|
||||
}
|
||||
}
|
||||
|
||||
PhyEntity::PhyFieldRxStatus
|
||||
@@ -375,8 +782,7 @@ 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));
|
||||
m_endPreambleDetectionEvents.push_back (Simulator::Schedule (m_wifiPhy->GetPreambleDetectionDuration (), &PhyEntity::EndPreambleDetectionPeriod, this, event));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -424,11 +830,11 @@ PhyEntity::EndPreambleDetectionPeriod (Ptr<Event> event)
|
||||
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)
|
||||
//A bit convoluted but it enables to sync all PHYs
|
||||
for (auto & it : m_wifiPhy->m_phyEntities)
|
||||
{
|
||||
endPreambleDetectionEvent.Cancel ();
|
||||
it.second->CancelRunningEndPreambleDetectionEvents (true);
|
||||
}
|
||||
m_wifiPhy->m_endPreambleDetectionEvents.clear ();
|
||||
|
||||
for (auto it = m_wifiPhy->m_currentPreambleEvents.begin (); it != m_wifiPhy->m_currentPreambleEvents.end (); )
|
||||
{
|
||||
@@ -471,7 +877,7 @@ PhyEntity::EndPreambleDetectionPeriod (Ptr<Event> event)
|
||||
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 ()));
|
||||
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
|
||||
@@ -495,22 +901,84 @@ PhyEntity::IsConfigSupported (Ptr<const WifiPpdu> ppdu) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::CancelAllEvents (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
|
||||
{
|
||||
endPreambleDetectionEvent.Cancel ();
|
||||
}
|
||||
m_endPreambleDetectionEvents.clear ();
|
||||
for (auto & endRxPayloadEvent : m_endRxPayloadEvents)
|
||||
{
|
||||
endRxPayloadEvent.Cancel ();
|
||||
}
|
||||
m_endRxPayloadEvents.clear ();
|
||||
}
|
||||
|
||||
bool
|
||||
PhyEntity::NoEndPreambleDetectionEvents (void) const
|
||||
{
|
||||
return m_endPreambleDetectionEvents.empty ();
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::CancelRunningEndPreambleDetectionEvents (bool clear /* = false */)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << clear);
|
||||
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
|
||||
{
|
||||
if (endPreambleDetectionEvent.IsRunning ())
|
||||
{
|
||||
endPreambleDetectionEvent.Cancel ();
|
||||
}
|
||||
}
|
||||
if (clear)
|
||||
{
|
||||
m_endPreambleDetectionEvents.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::AbortCurrentReception (WifiPhyRxfailureReason reason)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << reason);
|
||||
//TODO cancel some events here later on
|
||||
DoAbortCurrentReception (reason);
|
||||
m_wifiPhy->AbortCurrentReception (reason);
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::DoAbortCurrentReception (WifiPhyRxfailureReason reason)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << reason);
|
||||
if (m_wifiPhy->m_currentEvent) //Otherwise abort has already been called just before with FILTERED reason
|
||||
{
|
||||
for (auto & endMpduEvent : m_endOfMpduEvents)
|
||||
{
|
||||
endMpduEvent.Cancel ();
|
||||
}
|
||||
m_endOfMpduEvents.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::ResetReceive (Ptr<Event> event)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *event);
|
||||
NS_ASSERT (event->GetEndTime () == Simulator::Now ()); //TODO: overload for UL MU
|
||||
DoResetReceive (event);
|
||||
NS_ASSERT (m_endRxPayloadEvents.size () == 1 && m_endRxPayloadEvents.front ().IsExpired ());
|
||||
m_endRxPayloadEvents.clear ();
|
||||
m_wifiPhy->ResetReceive (event);
|
||||
}
|
||||
|
||||
void
|
||||
PhyEntity::DoResetReceive (Ptr<Event> event)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *event);
|
||||
NS_ASSERT (event->GetEndTime () == Simulator::Now ());
|
||||
}
|
||||
|
||||
double
|
||||
PhyEntity::GetRandomValue (void) const
|
||||
{
|
||||
@@ -523,4 +991,10 @@ PhyEntity::GetRxPowerWForPpdu (Ptr<Event> event) const
|
||||
return event->GetRxPowerW (m_wifiPhy->GetBand (m_wifiPhy->GetMeasurementChannelWidth (event->GetPpdu ())));
|
||||
}
|
||||
|
||||
Ptr<const Event>
|
||||
PhyEntity::GetCurrentEvent (void) const
|
||||
{
|
||||
return m_wifiPhy->m_currentEvent;
|
||||
}
|
||||
|
||||
} //namespace ns3
|
||||
|
||||
@@ -339,6 +339,19 @@ public:
|
||||
*/
|
||||
virtual Ptr<const WifiPsdu> GetAddressedPsduInPpdu (Ptr<const WifiPpdu> ppdu) const;
|
||||
|
||||
/**
|
||||
* Start receiving the PHY preamble of a PPDU (i.e. the first bit of the preamble has arrived).
|
||||
*
|
||||
* This method triggers the start of the preamble detection period (\see
|
||||
* StartPreambleDetectionPeriod) if the PHY can process the PPDU.
|
||||
*
|
||||
* \param ppdu the arriving PPDU
|
||||
* \param rxPowersW the receive power in W per band
|
||||
* \param rxDuration the duration of the PPDU
|
||||
* \param psdFlag the flag indicating the type of Tx PSD to build
|
||||
*/
|
||||
virtual void StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxPowersW,
|
||||
Time rxDuration, TxPsdFlag psdFlag);
|
||||
/**
|
||||
* Start receiving a given field.
|
||||
*
|
||||
@@ -367,6 +380,44 @@ public:
|
||||
*/
|
||||
void EndReceiveField (WifiPpduField field, Ptr<Event> event);
|
||||
|
||||
/**
|
||||
* The last symbol of the PPDU has arrived.
|
||||
*
|
||||
* \param event the event holding incoming PPDU's information
|
||||
*/
|
||||
void EndReceivePayload (Ptr<Event> event);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Cancel and clear all running events.
|
||||
*/
|
||||
virtual void CancelAllEvents (void);
|
||||
/**
|
||||
* \return \c true if there is no end preamble detection event running, \c false otherwise
|
||||
*/
|
||||
bool NoEndPreambleDetectionEvents (void) const;
|
||||
/**
|
||||
* Cancel and eventually clear all end preamble detection events.
|
||||
*
|
||||
* \param clear whether to clear the end preamble detection events' list
|
||||
*/
|
||||
void CancelRunningEndPreambleDetectionEvents (bool clear = false);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
virtual uint16_t GetStaId (const Ptr<const WifiPpdu> ppdu) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* A map of PPDU field elements per preamble type.
|
||||
@@ -404,16 +455,16 @@ protected:
|
||||
virtual PhyFieldRxStatus DoEndReceiveField (WifiPpduField field, Ptr<Event> event);
|
||||
|
||||
/**
|
||||
* Start receiving the preamble, perform amendment-specific actions, and
|
||||
* signify if it is supported.
|
||||
* Get the event corresponding to the incoming PPDU.
|
||||
*
|
||||
* This method triggers the start of the preamble detection period (\see
|
||||
* StartPreambleDetectionPeriod).
|
||||
* We store all incoming preamble events, perform amendment-specific actions,
|
||||
* and a decision is made at the end of the preamble detection window.
|
||||
*
|
||||
* \param event the event holding incoming PPDU's information
|
||||
* \return \c true if the preamble is supported, \c false otherwise
|
||||
* \param ppdu the incoming PPDU
|
||||
* \param rxPowersW the receive power in W per band
|
||||
* \return the event holding the incoming PPDU's information
|
||||
*/
|
||||
virtual bool DoStartReceivePreamble (Ptr<Event> event);
|
||||
virtual Ptr<Event> DoGetEvent (Ptr<const WifiPpdu> ppdu, RxPowerWattPerChannelBand rxPowersW);
|
||||
/**
|
||||
* End receiving the preamble, perform amendment-specific actions, and
|
||||
* provide the status of the reception.
|
||||
@@ -439,6 +490,37 @@ protected:
|
||||
*/
|
||||
void EndPreambleDetectionPeriod (Ptr<Event> event);
|
||||
|
||||
/**
|
||||
* Start receiving the PSDU (i.e. the first symbol of the PSDU has arrived).
|
||||
*
|
||||
* \param event the event holding incoming PPDU's information
|
||||
*/
|
||||
void StartReceivePayload (Ptr<Event> event);
|
||||
|
||||
/**
|
||||
* Start receiving the PSDU (i.e. the first symbol of the PSDU has arrived)
|
||||
* and perform amendment-specific actions.
|
||||
*
|
||||
* \param event the event holding incoming PPDU's information
|
||||
*/
|
||||
virtual void DoStartReceivePayload (Ptr<Event> event);
|
||||
|
||||
/**
|
||||
* Perform amendment-specific actions before resetting 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
|
||||
*/
|
||||
virtual void DoResetReceive (Ptr<Event> event);
|
||||
|
||||
/**
|
||||
* Perform amendment-specific actions before aborting the
|
||||
* current reception.
|
||||
*
|
||||
* \param reason the reason the reception is aborted
|
||||
*/
|
||||
virtual void DoAbortCurrentReception (WifiPhyRxfailureReason reason);
|
||||
|
||||
/**
|
||||
* Checks if the signaled configuration (excluding bandwidth)
|
||||
* is supported by the PHY.
|
||||
@@ -448,18 +530,82 @@ protected:
|
||||
*/
|
||||
virtual bool IsConfigSupported (Ptr<const WifiPpdu> ppdu) const;
|
||||
|
||||
/**
|
||||
* Drop the PPDU and the corresponding preamble detection event, but keep CCA busy
|
||||
* state after the completion of the currently processed event.
|
||||
*
|
||||
* \param ppdu the incoming PPDU
|
||||
* \param reason the reason the PPDU is dropped
|
||||
* \param endRx the end of the incoming PPDU's reception
|
||||
* \param measurementChannelWidth the measurement width (in MHz) to consider for the PPDU
|
||||
*/
|
||||
void DropPreambleEvent (Ptr<const WifiPpdu> ppdu, WifiPhyRxfailureReason reason, Time endRx, uint16_t measurementChannelWidth);
|
||||
|
||||
/**
|
||||
* Erase the event corresponding to the PPDU from the list of preamble events,
|
||||
* but consider it as noise after the completion of the current event.
|
||||
*
|
||||
* \param ppdu the incoming PPDU
|
||||
* \param rxDuration the duration of the PPDU
|
||||
*/
|
||||
void ErasePreambleEvent (Ptr<const WifiPpdu> ppdu, Time rxDuration);
|
||||
|
||||
/**
|
||||
* Get the reception status for the provided MPDU and notify.
|
||||
*
|
||||
* \param psdu the arriving MPDU formatted as a PSDU
|
||||
* \param event the event holding incoming PPDU's information
|
||||
* \param staId the station ID of the PSDU (only used for MU)
|
||||
* \param relativeMpduStart the relative start time of the MPDU within the A-MPDU. 0 for normal MPDUs
|
||||
* \param mpduDuration the duration of the MPDU
|
||||
*
|
||||
* \return information on MPDU reception: status, signal power (dBm), and noise power (in dBm)
|
||||
*/
|
||||
std::pair<bool, SignalNoiseDbm> GetReceptionStatus (Ptr<const WifiPsdu> psdu,
|
||||
Ptr<Event> event, uint16_t staId,
|
||||
Time relativeMpduStart,
|
||||
Time mpduDuration);
|
||||
/**
|
||||
* The last symbol of an MPDU in an A-MPDU has arrived.
|
||||
*
|
||||
* \param event the event holding incoming PPDU's information
|
||||
* \param psdu the arriving MPDU formatted as a PSDU containing a normal MPDU
|
||||
* \param mpduIndex the index of the MPDU within the A-MPDU
|
||||
* \param relativeStart the relative start time of the MPDU within the A-MPDU.
|
||||
* \param mpduDuration the duration of the MPDU
|
||||
*/
|
||||
void EndOfMpdu (Ptr<Event> event, Ptr<const WifiPsdu> psdu, size_t mpduIndex, Time relativeStart, Time mpduDuration);
|
||||
|
||||
/**
|
||||
* Schedule end of MPDUs events.
|
||||
*
|
||||
* \param event the event holding incoming PPDU's information
|
||||
*/
|
||||
void ScheduleEndOfMpdus (Ptr<Event> event);
|
||||
|
||||
/**
|
||||
* Perform amendment-specific actions at the end of the reception of
|
||||
* the payload.
|
||||
*
|
||||
* \param ppdu the incoming PPDU
|
||||
*/
|
||||
virtual void DoEndReceivePayload (Ptr<const WifiPpdu> ppdu);
|
||||
|
||||
/**
|
||||
* Get the channel width and band to use (will be overloaded by child classes).
|
||||
*
|
||||
* \param txVector the transmission parameters
|
||||
* \param staId the station ID of the PSDU
|
||||
* \return a pair of channel width (MHz) and band
|
||||
*/
|
||||
virtual std::pair<uint16_t, WifiSpectrumBand> GetChannelWidthAndBand (WifiTxVector txVector, uint16_t staId) 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.
|
||||
@@ -485,11 +631,68 @@ protected:
|
||||
* \return the received power (W) for the event over a given band
|
||||
*/
|
||||
double GetRxPowerWForPpdu (Ptr<Event> event) const;
|
||||
/**
|
||||
* Get the pointer to the current event (stored in WifiPhy).
|
||||
* Wrapper used by child classes.
|
||||
*
|
||||
* \return the pointer to the current event
|
||||
*/
|
||||
Ptr<const Event> GetCurrentEvent (void) const;
|
||||
/**
|
||||
* Get the map of current preamble events (stored in WifiPhy).
|
||||
* Wrapper used by child classes.
|
||||
*
|
||||
* \return the reference to the map of current preamble events
|
||||
*/
|
||||
const std::map <std::pair<uint64_t, WifiPreamble>, Ptr<Event> > & GetCurrentPreambleEvents (void) const;
|
||||
/**
|
||||
* Add an entry to the map of current preamble events (stored in WifiPhy).
|
||||
* Wrapper used by child classes.
|
||||
*
|
||||
* \param event the event holding incoming PPDU's information
|
||||
*/
|
||||
void AddPreambleEvent (Ptr<Event> event);
|
||||
|
||||
/**
|
||||
* Create an event using WifiPhy's InterferenceHelper class.
|
||||
* Wrapper used by child classes.
|
||||
*
|
||||
* \copydoc InterferenceHelper::Add(Ptr<const WifiPpdu>, WifiTxVector, Time, RxPowerWattPerChannelBand, bool)
|
||||
*/
|
||||
Ptr<Event> CreateInterferenceEvent (Ptr<const WifiPpdu> ppdu, WifiTxVector txVector, Time duration, RxPowerWattPerChannelBand rxPower, bool isStartOfdmaRxing = false);
|
||||
/**
|
||||
* Update an event in WifiPhy's InterferenceHelper class.
|
||||
* Wrapper used by child classes.
|
||||
*
|
||||
* \copydoc InterferenceHelper::UpdateEvent(Ptr<Event>, RxPowerWattPerChannelBand)
|
||||
*/
|
||||
void UpdateInterferenceEvent (Ptr<Event> event, RxPowerWattPerChannelBand rxPower);
|
||||
/**
|
||||
* Notify WifiPhy's InterferenceHelper of the end of the reception,
|
||||
* clear maps and end of MPDU event, and eventually reset WifiPhy.
|
||||
*
|
||||
* \param reset whether to reset WifiPhy
|
||||
*/
|
||||
void NotifyInterferenceRxEndAndClear (bool reset);
|
||||
|
||||
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
|
||||
|
||||
std::vector <EventId> m_endPreambleDetectionEvents; //!< the end of preamble detection events
|
||||
std::vector <EventId> m_endOfMpduEvents; //!< the end of MPDU events (only used for A-MPDUs)
|
||||
|
||||
std::vector <EventId> m_endRxPayloadEvents; //!< the end of receive events (only one unless UL MU reception)
|
||||
|
||||
/**
|
||||
* A pair of a UID and STA_ID
|
||||
*/
|
||||
typedef std::pair <uint64_t /* UID */, uint16_t /* STA-ID */> UidStaIdPair;
|
||||
|
||||
std::map<UidStaIdPair, std::vector<bool> > m_statusPerMpduMap; //!< Map of the current reception status per MPDU that is filled in as long as MPDUs are being processed by the PHY in case of an A-MPDU
|
||||
std::map<UidStaIdPair, SignalNoiseDbm> m_signalNoiseMap; //!< Map of the latest signal power and noise power in dBm (noise power includes the noise figure)
|
||||
|
||||
}; //class PhyEntity
|
||||
|
||||
/**
|
||||
|
||||
@@ -1061,6 +1061,15 @@ public:
|
||||
*/
|
||||
WifiSpectrumBand GetNonOfdmaBand (WifiTxVector txVector, uint16_t staId) const;
|
||||
|
||||
/**
|
||||
* \param channelWidth the total channel width (MHz) used for the OFDMA transmission
|
||||
* \param range the subcarrier range of the HE RU
|
||||
* \return the converted subcarriers
|
||||
*
|
||||
* This is a helper function to convert HE RU subcarriers, which are relative to the center frequency subcarrier, to the indexes used by the Spectrum model.
|
||||
*/
|
||||
virtual WifiSpectrumBand ConvertHeRuSubcarriers (uint16_t channelWidth, HeRu::SubcarrierRange range) const;
|
||||
|
||||
/**
|
||||
* Add the PHY entity to the map of __implemented__ PHY entities for the
|
||||
* given modulation class.
|
||||
@@ -1132,7 +1141,6 @@ 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.
|
||||
@@ -1141,7 +1149,6 @@ public: //TODO find a better way (robust enough for OfdmaSpectrumWifiPhy overloa
|
||||
* \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
|
||||
@@ -1162,15 +1169,6 @@ protected:
|
||||
*/
|
||||
virtual WifiSpectrumBand GetBand (uint16_t bandWidth, uint8_t bandIndex = 0);
|
||||
|
||||
/**
|
||||
* \param channelWidth the total channel width (MHz) used for the OFDMA transmission
|
||||
* \param range the subcarrier range of the HE RU
|
||||
* \return the converted subcarriers
|
||||
*
|
||||
* This is a helper function to convert HE RU subcarriers, which are relative to the center frequency subcarrier, to the indexes used by the Spectrum model.
|
||||
*/
|
||||
virtual WifiSpectrumBand ConvertHeRuSubcarriers (uint16_t channelWidth, HeRu::SubcarrierRange range) const;
|
||||
|
||||
/**
|
||||
* Add the PHY entity to the map of supported PHY entities for the
|
||||
* given modulation class for the WifiPhy instance.
|
||||
|
||||
Reference in New Issue
Block a user