wifi: Handle multiple HE TB preambles

This commit is contained in:
Sébastien Deronne
2019-07-31 20:33:06 +02:00
parent ce7f3ac3a5
commit 6de4e8d7f5
8 changed files with 358 additions and 115 deletions

View File

@@ -108,6 +108,22 @@ Event::GetTxVector (void) const
return m_txVector;
}
void
Event::UpdateRxPowerW (RxPowerWattPerChannelBand rxPower)
{
NS_ASSERT (rxPower.size () == m_rxPowerW.size ());
//Update power band per band
for (auto & currentRxPowerW : m_rxPowerW)
{
auto band = currentRxPowerW.first;
auto it = rxPower.find (band);
if (it != rxPower.end ())
{
currentRxPowerW.second += it->second;
}
}
}
std::ostream & operator << (std::ostream &os, const Event &event)
{
os << "start=" << event.GetStartTime () << ", end=" << event.GetEndTime ()
@@ -229,7 +245,7 @@ InterferenceHelper::SetNumberOfReceiveAntennas (uint8_t rx)
}
Time
InterferenceHelper::GetEnergyDuration (double energyW, WifiSpectrumBand band) const
InterferenceHelper::GetEnergyDuration (double energyW, WifiSpectrumBand band)
{
Time now = Simulator::Now ();
auto i = GetPreviousPosition (now, band);
@@ -251,7 +267,7 @@ InterferenceHelper::GetEnergyDuration (double energyW, WifiSpectrumBand band) co
void
InterferenceHelper::AppendEvent (Ptr<Event> event)
{
NS_LOG_FUNCTION (this);
NS_LOG_FUNCTION (this << event);
RxPowerWattPerChannelBand rxPowerWattPerChannelBand = event->GetRxPowerWPerBand ();
for (auto const& it : rxPowerWattPerChannelBand)
{
@@ -277,6 +293,26 @@ InterferenceHelper::AppendEvent (Ptr<Event> event)
}
}
void
InterferenceHelper::UpdateEvent (Ptr<Event> event, RxPowerWattPerChannelBand rxPower)
{
NS_LOG_FUNCTION (this << event);
//This is called for UL MU events, in order to scale power as long as UL MU PPDUs arrive
for (auto const& it : rxPower)
{
WifiSpectrumBand band = it.first;
auto ni_it = m_niChangesPerBand.find (band);
NS_ASSERT (ni_it != m_niChangesPerBand.end ());
auto first = GetPreviousPosition (event->GetStartTime (), band);
auto last = GetPreviousPosition (event->GetEndTime (), band);
for (auto i = first; i != last; ++i)
{
i->second.AddPower (it.second);
}
}
event->UpdateRxPowerW (rxPower);
}
double
InterferenceHelper::CalculateSnr (double signal, double noiseInterference, uint16_t channelWidth, uint8_t nss) const
{
@@ -901,16 +937,16 @@ InterferenceHelper::EraseEvents (void)
m_rxing = false;
}
InterferenceHelper::NiChanges::const_iterator
InterferenceHelper::GetNextPosition (Time moment, WifiSpectrumBand band) const
InterferenceHelper::NiChanges::iterator
InterferenceHelper::GetNextPosition (Time moment, WifiSpectrumBand band)
{
auto it = m_niChangesPerBand.find (band);
NS_ASSERT (it != m_niChangesPerBand.end ());
return it->second.upper_bound (moment);
}
InterferenceHelper::NiChanges::const_iterator
InterferenceHelper::GetPreviousPosition (Time moment, WifiSpectrumBand band) const
InterferenceHelper::NiChanges::iterator
InterferenceHelper::GetPreviousPosition (Time moment, WifiSpectrumBand band)
{
auto it = GetNextPosition (moment, band);
// This is safe since there is always an NiChange at time 0,
@@ -935,15 +971,15 @@ InterferenceHelper::NotifyRxStart ()
}
void
InterferenceHelper::NotifyRxEnd ()
InterferenceHelper::NotifyRxEnd (Time endTime)
{
NS_LOG_FUNCTION (this);
NS_LOG_FUNCTION (this << endTime);
m_rxing = false;
//Update m_firstPower for frame capture
//Update m_firstPowerPerBand for frame capture
for (auto ni : m_niChangesPerBand)
{
NS_ASSERT (ni.second.size () > 1);
auto it = GetPreviousPosition (Simulator::Now (), ni.first);
auto it = GetPreviousPosition (endTime, ni.first);
it--;
m_firstPowerPerBand.find (ni.first)->second = it->second.GetPower ();
}

View File

@@ -105,6 +105,13 @@ public:
* \return the TXVECTOR of the PPDU
*/
WifiTxVector GetTxVector (void) const;
/**
* Update the received power (W) for all bands, i.e. add up the received power
* to the current received power, for each band.
*
* \param the received power (W) for all bands.
*/
void UpdateRxPowerW (RxPowerWattPerChannelBand rxPower);
private:
@@ -195,7 +202,7 @@ public:
* energy on the medium for a given band will
* be higher than the requested threshold.
*/
Time GetEnergyDuration (double energyW, WifiSpectrumBand band) const;
Time GetEnergyDuration (double energyW, WifiSpectrumBand band);
/**
* Add the PPDU-related signal to interference helper.
@@ -270,13 +277,23 @@ public:
void NotifyRxStart ();
/**
* Notify that RX has ended.
*
* \param endTime the end time of the signal
*/
void NotifyRxEnd ();
void NotifyRxEnd (Time endTime);
/**
* Erase all events.
*/
void EraseEvents (void);
/**
* Update event to scale its received power (W) per band.
*
* \param event the event to be updated
* \param rxPower the received power (W) per band to be added to the current event
*/
void UpdateEvent (Ptr<Event> event, RxPowerWattPerChannelBand rxPower);
protected:
/**
@@ -359,6 +376,7 @@ private:
* \param event
*/
void AppendEvent (Ptr<Event> event);
/**
* Calculate noise and interference power in W.
*
@@ -434,7 +452,7 @@ private:
* \param band identify the band to check
* \returns an iterator to the list of NiChanges
*/
NiChanges::const_iterator GetNextPosition (Time moment, WifiSpectrumBand band) const;
NiChanges::iterator GetNextPosition (Time moment, WifiSpectrumBand band);
/**
* Returns an iterator to the last NiChange that is before than moment
*
@@ -442,7 +460,7 @@ private:
* \param band identify the band to check
* \returns an iterator to the list of NiChanges
*/
NiChanges::const_iterator GetPreviousPosition (Time moment, WifiSpectrumBand band) const;
NiChanges::iterator GetPreviousPosition (Time moment, WifiSpectrumBand band);
/**
* Add NiChange to the list at the appropriate position and

View File

@@ -510,7 +510,6 @@ WifiPhy::WifiPhy ()
m_rxMpduReferenceNumber (0xffffffff),
m_endRxEvent (),
m_endPhyRxEvent (),
m_endPreambleDetectionEvent (),
m_endTxEvent (),
m_standard (WIFI_PHY_STANDARD_UNSPECIFIED),
m_band (WIFI_PHY_BAND_UNSPECIFIED),
@@ -552,7 +551,11 @@ WifiPhy::DoDispose (void)
m_endTxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_endPhyRxEvent.Cancel ();
m_endPreambleDetectionEvent.Cancel ();
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
endPreambleDetectionEvent.Cancel ();
}
m_endPreambleDetectionEvents.clear ();
m_device = 0;
m_mobility = 0;
m_state = 0;
@@ -561,6 +564,7 @@ WifiPhy::DoDispose (void)
m_deviceRateSet.clear ();
m_deviceMcsSet.clear ();
m_mcsIndexMap.clear ();
m_currentPreambleEvents.clear ();
}
void
@@ -1677,6 +1681,8 @@ WifiPhy::DoChannelSwitch (uint8_t nch)
{
m_powerRestricted = false;
m_channelAccessRequested = false;
m_currentEvent = 0;
m_currentPreambleEvents.clear ();
if (!IsInitialized ())
{
//this is not channel switch, this is initialization
@@ -1691,7 +1697,11 @@ WifiPhy::DoChannelSwitch (uint8_t nch)
NS_LOG_DEBUG ("drop packet because of channel switching while reception");
m_endPhyRxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_endPreambleDetectionEvent.Cancel ();
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
endPreambleDetectionEvent.Cancel ();
}
m_endPreambleDetectionEvents.clear ();
goto switchChannel;
break;
case WifiPhyState::TX:
@@ -1700,9 +1710,12 @@ WifiPhy::DoChannelSwitch (uint8_t nch)
break;
case WifiPhyState::CCA_BUSY:
case WifiPhyState::IDLE:
if (m_endPreambleDetectionEvent.IsRunning ())
{
m_endPreambleDetectionEvent.Cancel ();
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
endPreambleDetectionEvent.Cancel ();
}
m_endPreambleDetectionEvents.clear ();
m_endRxEvent.Cancel ();
}
goto switchChannel;
@@ -1737,6 +1750,8 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency)
{
m_powerRestricted = false;
m_channelAccessRequested = false;
m_currentEvent = 0;
m_currentPreambleEvents.clear ();
if (!IsInitialized ())
{
//this is not channel switch, this is initialization
@@ -1751,7 +1766,11 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency)
NS_LOG_DEBUG ("drop packet because of channel/frequency switching while reception");
m_endPhyRxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_endPreambleDetectionEvent.Cancel ();
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
endPreambleDetectionEvent.Cancel ();
}
m_endPreambleDetectionEvents.clear ();
goto switchFrequency;
break;
case WifiPhyState::TX:
@@ -1760,11 +1779,12 @@ WifiPhy::DoFrequencySwitch (uint16_t frequency)
break;
case WifiPhyState::CCA_BUSY:
case WifiPhyState::IDLE:
if (m_endPreambleDetectionEvent.IsRunning ())
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
m_endPreambleDetectionEvent.Cancel ();
m_endRxEvent.Cancel ();
endPreambleDetectionEvent.Cancel ();
}
m_endPreambleDetectionEvents.clear ();
m_endRxEvent.Cancel ();
goto switchFrequency;
break;
case WifiPhyState::SLEEP:
@@ -1834,8 +1854,12 @@ WifiPhy::SetOffMode (void)
m_channelAccessRequested = false;
m_endPhyRxEvent.Cancel ();
m_endRxEvent.Cancel ();
m_endPreambleDetectionEvent.Cancel ();
m_endTxEvent.Cancel ();
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
endPreambleDetectionEvent.Cancel ();
}
m_endPreambleDetectionEvents.clear ();
m_state->SwitchToOff ();
}
@@ -1843,6 +1867,7 @@ void
WifiPhy::ResumeFromSleep (void)
{
NS_LOG_FUNCTION (this);
m_currentPreambleEvents.clear ();
switch (m_state->GetState ())
{
case WifiPhyState::TX:
@@ -2835,16 +2860,21 @@ WifiPhy::Send (WifiConstPsduMap psdus, WifiTxVector txVector)
txDuration = CalculateTxDuration (psdus, txVector, GetPhyBand ());
}
if ((m_currentEvent != 0) && (m_currentEvent->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ())))
if (!m_endPreambleDetectionEvents.empty () || ((m_currentEvent != 0) && (m_currentEvent->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ()))))
{
AbortCurrentReception (RECEPTION_ABORTED_BY_TX);
//that packet will be noise _after_ the transmission.
MaybeCcaBusyDuration ();
}
if (m_currentEvent != 0)
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
AbortCurrentReception (RECEPTION_ABORTED_BY_TX);
if (endPreambleDetectionEvent.IsRunning ())
{
endPreambleDetectionEvent.Cancel ();
}
}
m_currentPreambleEvents.clear ();
if (m_powerRestricted)
{
@@ -2895,6 +2925,16 @@ WifiPhy::Send (WifiConstPsduMap psdus, WifiTxVector txVector)
m_channelAccessRequested = false;
m_powerRestricted = false;
Simulator::Schedule (txDuration, &WifiPhy::Reset, this);
}
void
WifiPhy::Reset (void)
{
NS_LOG_FUNCTION (this);
m_currentPreambleEvents.clear ();
m_currentEvent = 0;
}
void
@@ -2903,51 +2943,122 @@ WifiPhy::StartReceiveHeader (Ptr<Event> event)
NS_LOG_FUNCTION (this << *event);
NS_ASSERT (!IsStateRx ());
NS_ASSERT (m_endPhyRxEvent.IsExpired ());
NS_ASSERT (m_currentEvent != 0);
NS_ASSERT (event->GetStartTime () == m_currentEvent->GetStartTime ());
NS_ASSERT (event->GetEndTime () == m_currentEvent->GetEndTime ());
uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth ();
auto primaryBand = GetBand (primaryChannelWidth);
double maxRxPowerW = 0;
Ptr<Event> maxEvent;
for (auto preambleEvent : m_currentPreambleEvents)
{
double rxPowerW = preambleEvent.second->GetRxPowerW (primaryBand);
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 ());
NotifyRxDrop (GetAddressedPsduInPpdu (event->GetPpdu ()), BUSY_DECODING_PREAMBLE);
auto it = m_currentPreambleEvents.find (std::make_pair (event->GetPpdu ()->GetUid (), event->GetPpdu ()->GetPreamble ()));
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_interference.NotifyRxEnd (maxEvent->GetStartTime ());
//Make sure InterferenceHelper keeps recording events
m_interference.NotifyRxStart ();
return;
}
m_currentEvent = event;
uint16_t channelWidth;
if (event->GetTxVector ().GetChannelWidth () >= 40)
if (m_currentEvent->GetTxVector ().GetChannelWidth () >= 40)
{
channelWidth = 20; //calculate PER on the 20 MHz primary channel for PHY headers
}
else
{
channelWidth = event->GetTxVector ().GetChannelWidth ();
channelWidth = m_currentEvent->GetTxVector ().GetChannelWidth ();
}
auto band = GetBand (channelWidth);
InterferenceHelper::SnrPer snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (event, band);
InterferenceHelper::SnrPer snrPer = m_interference.CalculateNonHtPhyHeaderSnrPer (m_currentEvent, band);
double snr = snrPer.snr;
NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per);
NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr));
if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (event->GetRxPowerW (band), snr, m_channelWidth)))
Time headerPayloadDuration = m_currentEvent->GetDuration () - (Simulator::Now () - m_currentEvent->GetStartTime ()); //startOfPreambleDuration;
if (!m_preambleDetectionModel || (m_preambleDetectionModel->IsPreambleDetected (m_currentEvent->GetRxPowerW (band), snr, m_channelWidth)))
{
NotifyRxBegin (GetAddressedPsduInPpdu (event->GetPpdu ()), event->GetRxPowerWPerBand ());
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
endPreambleDetectionEvent.Cancel ();
}
m_endPreambleDetectionEvents.clear ();
for (auto it = m_currentPreambleEvents.begin (); it != m_currentPreambleEvents.end (); )
{
if (it->second != 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_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_interference.NotifyRxEnd (m_currentEvent->GetStartTime ());
}
else
{
reason = BUSY_DECODING_PREAMBLE;
}
NotifyRxDrop (GetAddressedPsduInPpdu (it->second->GetPpdu ()), reason);
it = m_currentPreambleEvents.erase (it);
}
else
{
it++;
}
}
//Make sure InterferenceHelper keeps recording events
m_interference.NotifyRxStart ();
NotifyRxBegin (GetAddressedPsduInPpdu (m_currentEvent->GetPpdu ()), m_currentEvent->GetRxPowerWPerBand ());
m_timeLastPreambleDetected = Simulator::Now ();
WifiTxVector txVector = event->GetTxVector ();
WifiTxVector txVector = m_currentEvent->GetTxVector ();
if (txVector.GetPreambleType () == WIFI_PREAMBLE_HT_GF)
{
//No non-HT PHY header for HT GF
Time remainingPreambleHeaderDuration = CalculatePhyPreambleAndHeaderDuration (txVector) - GetPreambleDetectionDuration ();
Time remainingPreambleHeaderDuration = CalculatePhyPreambleAndHeaderDuration (txVector) - (Simulator::Now () - m_currentEvent->GetStartTime ());
m_state->SwitchMaybeToCcaBusy (remainingPreambleHeaderDuration);
m_endPhyRxEvent = Simulator::Schedule (remainingPreambleHeaderDuration, &WifiPhy::StartReceivePayload, this, event);
m_endPhyRxEvent = Simulator::Schedule (remainingPreambleHeaderDuration, &WifiPhy::StartReceivePayload, this, m_currentEvent);
}
else
{
//Schedule end of non-HT PHY header
Time remainingPreambleAndNonHtHeaderDuration = GetPhyPreambleDuration (txVector) + GetPhyHeaderDuration (txVector) - GetPreambleDetectionDuration ();
Time remainingPreambleAndNonHtHeaderDuration = GetPhyPreambleDuration (txVector) + GetPhyHeaderDuration (txVector) - (Simulator::Now () - m_currentEvent->GetStartTime ());
m_state->SwitchMaybeToCcaBusy (remainingPreambleAndNonHtHeaderDuration);
m_endPhyRxEvent = Simulator::Schedule (remainingPreambleAndNonHtHeaderDuration, &WifiPhy::ContinueReceiveHeader, this, event);
m_endPhyRxEvent = Simulator::Schedule (remainingPreambleAndNonHtHeaderDuration, &WifiPhy::ContinueReceiveHeader, this, m_currentEvent);
}
}
else
{
NS_LOG_DEBUG ("Drop packet because PHY preamble detection failed");
NotifyRxDrop (GetAddressedPsduInPpdu (event->GetPpdu ()), PREAMBLE_DETECT_FAILURE);
m_interference.NotifyRxEnd ();
NotifyRxDrop (GetAddressedPsduInPpdu (m_currentEvent->GetPpdu ()), PREAMBLE_DETECT_FAILURE);
m_interference.NotifyRxEnd (Simulator::Now ());
for (auto it = m_currentPreambleEvents.begin (); it != m_currentPreambleEvents.end (); ++it)
{
if (it->second == m_currentEvent)
{
it = m_currentPreambleEvents.erase (it);
break;
}
}
m_currentEvent = 0;
// Like CCA-SD, CCA-ED is governed by the 4μs CCA window to flag CCA-BUSY
@@ -2990,6 +3101,7 @@ WifiPhy::ContinueReceiveHeader (Ptr<Event> event)
{
NS_LOG_DEBUG ("Abort reception because non-HT PHY header reception failed");
AbortCurrentReception (L_SIG_FAILURE);
m_currentPreambleEvents.clear ();
if (event->GetEndTime () > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
{
MaybeCcaBusyDuration ();
@@ -3008,9 +3120,58 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
NS_LOG_FUNCTION (this << *ppdu << it->second);
WifiTxVector txVector = ppdu->GetTxVector ();
Time rxDuration = ppdu->GetTxDuration ();
Ptr<Event> event = m_interference.Add (ppdu, txVector, rxDuration, rxPowersW);
Time endRx = Simulator::Now () + rxDuration;
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.
auto uidPreamblePair = std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ());
if (ppdu->IsUlMu ())
{
auto it = m_currentPreambleEvents.find (uidPreamblePair);
if (it != m_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 STAs 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 = m_interference.Add (ppdu, txVector, rxDuration, rxPowersW);
NS_LOG_DEBUG ("Drop packet because not received within the 400ns window");
NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), HE_TB_PPDU_TOO_LATE);
}
else
{
//Update received power of the event associated to that UL MU transmission
m_interference.UpdateEvent (event, rxPowersW);
}
if ((m_currentEvent != 0) && (m_currentEvent->GetPpdu ()->GetUid () != ppdu->GetUid ()))
{
NS_LOG_DEBUG ("Drop packet because already receiving another HE TB PPDU");
NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), RXING);
}
return;
}
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 = m_interference.Add (ppdu, txVector, rxDuration, rxPowersW);
m_currentPreambleEvents.insert ({std::make_pair (ppdu->GetUid (), ppdu->GetPreamble ()), event});
}
}
else
{
event = m_interference.Add (ppdu, txVector, rxDuration, rxPowersW);
NS_ASSERT (m_currentPreambleEvents.find (uidPreamblePair) == m_currentPreambleEvents.end ());
m_currentPreambleEvents.insert ({uidPreamblePair, event});
}
Time endRx = Simulator::Now () + rxDuration;
if (m_state->GetState () == WifiPhyState::OFF)
{
NS_LOG_DEBUG ("Cannot start RX because device is OFF");
@@ -3031,18 +3192,6 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
return;
}
if (!txVector.GetModeInitialized ())
{
//If SetRate method was not called above when filling in txVector, this means the PHY does support the rate indicated in PHY SIG headers
NS_LOG_DEBUG ("drop packet because of unsupported RX mode");
NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), UNSUPPORTED_SETTINGS);
if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
{
MaybeCcaBusyDuration ();
}
return;
}
switch (m_state->GetState ())
{
case WifiPhyState::SWITCHING:
@@ -3063,7 +3212,6 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
}
break;
case WifiPhyState::RX:
NS_ASSERT (m_currentEvent != 0);
if (m_frameCaptureModel != 0
&& m_frameCaptureModel->IsInCaptureWindow (m_timeLastPreambleDetected)
&& m_frameCaptureModel->CaptureNewFrame (m_currentEvent, event))
@@ -3076,6 +3224,16 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
{
NS_LOG_DEBUG ("Drop packet because already in Rx");
NotifyRxDrop (GetAddressedPsduInPpdu (ppdu), RXING);
if (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_currentPreambleEvents.clear ();
}
if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
{
//that packet will be noise _after_ the reception of the currently-received packet.
@@ -3105,8 +3263,8 @@ WifiPhy::StartReceivePreamble (Ptr<WifiPpdu> ppdu, RxPowerWattPerChannelBand rxP
}
else
{
NS_LOG_DEBUG ("Drop packet because already in Rx");
NotifyRxDrop (ppdu->GetPsdu (), RXING);
NS_LOG_DEBUG ("Drop packet because already decoding preamble");
NotifyRxDrop (ppdu->GetPsdu (), BUSY_DECODING_PREAMBLE);
if (endRx > (Simulator::Now () + m_state->GetDelayUntilIdle ()))
{
//that packet will be noise _after_ the reception of the currently-received packet.
@@ -3223,7 +3381,7 @@ WifiPhy::StartReceivePayload (Ptr<Event> event)
else //mode is not allowed
{
NS_LOG_DEBUG ("Drop packet because it was sent using an unsupported mode (" << txMode << ")");
NotifyRxDrop (psdu, UNSUPPORTED_SETTINGS);
NotifyRxDrop (GetAddressedPsduInPpdu (event->GetPpdu ()), UNSUPPORTED_SETTINGS);
}
}
else
@@ -3375,8 +3533,9 @@ WifiPhy::EndReceive (Ptr<Event> event)
m_state->SwitchFromRxEndError (Copy (psdu), snr);
}
m_interference.NotifyRxEnd ();
m_interference.NotifyRxEnd (Simulator::Now ());
m_currentEvent = 0;
m_currentPreambleEvents.clear ();
MaybeCcaBusyDuration ();
}
@@ -3400,7 +3559,7 @@ WifiPhy::GetReceptionStatus (Ptr<const WifiPsdu> psdu, Ptr<Event> event, uint16_
InterferenceHelper::SnrPer snrPer = m_interference.CalculatePayloadSnrPer (event, channelWidth, band, staId, std::make_pair (relativeMpduStart, relativeMpduStart + mpduDuration));
WifiMode mode = event->GetTxVector ().GetMode (staId);
NS_LOG_DEBUG ("mode=" << (mode.GetDataRate (event->GetTxVector (), 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));
@@ -3466,8 +3625,9 @@ WifiPhy::ResetReceive (Ptr<Event> event)
NS_ASSERT (event->GetEndTime () == Simulator::Now ());
}
NS_ASSERT (!IsStateRx ());
m_interference.NotifyRxEnd ();
m_interference.NotifyRxEnd (Simulator::Now ());
m_currentEvent = 0;
m_currentPreambleEvents.clear ();
MaybeCcaBusyDuration ();
}
@@ -4725,10 +4885,14 @@ void
WifiPhy::AbortCurrentReception (WifiPhyRxfailureReason reason)
{
NS_LOG_FUNCTION (this << reason);
if (m_endPreambleDetectionEvent.IsRunning ())
for (auto & endPreambleDetectionEvent : m_endPreambleDetectionEvents)
{
m_endPreambleDetectionEvent.Cancel ();
if (endPreambleDetectionEvent.IsRunning ())
{
endPreambleDetectionEvent.Cancel ();
}
}
m_endPreambleDetectionEvents.clear ();
if (m_endPhyRxEvent.IsRunning ())
{
m_endPhyRxEvent.Cancel ();
@@ -4737,12 +4901,24 @@ WifiPhy::AbortCurrentReception (WifiPhyRxfailureReason reason)
{
m_endRxEvent.Cancel ();
}
m_interference.NotifyRxEnd (Simulator::Now ());
if (!m_currentEvent)
{
return;
}
NotifyRxDrop (GetAddressedPsduInPpdu (m_currentEvent->GetPpdu ()), reason);
m_interference.NotifyRxEnd ();
if (reason == OBSS_PD_CCA_RESET)
{
m_state->SwitchFromRxAbort ();
}
for (auto it = m_currentPreambleEvents.begin (); it != m_currentPreambleEvents.end (); ++it)
{
if (it->second == m_currentEvent)
{
it = m_currentPreambleEvents.erase (it);
break;
}
}
m_currentEvent = 0;
}
@@ -4782,38 +4958,11 @@ WifiPhy::GetTxPowerForTransmission (WifiTxVector txVector) const
void
WifiPhy::StartRx (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
uint16_t primaryChannelWidth = GetChannelWidth () >= 40 ? 20 : GetChannelWidth ();
auto primaryBand = GetBand (primaryChannelWidth);
double rxPowerW = event->GetRxPowerW (primaryBand);
NS_LOG_FUNCTION (this << *event << rxPowerW);
NS_LOG_DEBUG ("sync to signal (power=" << rxPowerW << "W)");
NS_LOG_DEBUG ("sync to signal (power=" << event->GetRxPowerW (GetBand (primaryChannelWidth)) << "W)");
m_interference.NotifyRxStart (); //We need to notify it now so that it starts recording events
if (!m_endPreambleDetectionEvent.IsRunning ())
{
Time startOfPreambleDuration = GetPreambleDetectionDuration ();
Time remainingRxDuration = event->GetDuration () - startOfPreambleDuration;
m_endPreambleDetectionEvent = Simulator::Schedule (startOfPreambleDuration, &WifiPhy::StartReceiveHeader, this, event);
}
else if ((m_frameCaptureModel != 0) && (rxPowerW > m_currentEvent->GetRxPowerW (primaryBand)))
{
NS_LOG_DEBUG ("Received a stronger signal during preamble detection: drop current packet and switch to new packet");
NotifyRxDrop (GetAddressedPsduInPpdu (m_currentEvent->GetPpdu ()), PREAMBLE_DETECTION_PACKET_SWITCH);
m_interference.NotifyRxEnd ();
m_endPreambleDetectionEvent.Cancel ();
m_interference.NotifyRxStart ();
Time startOfPreambleDuration = GetPreambleDetectionDuration ();
Time remainingRxDuration = event->GetDuration () - startOfPreambleDuration;
m_endPreambleDetectionEvent = Simulator::Schedule (startOfPreambleDuration, &WifiPhy::StartReceiveHeader, this, event);
}
else
{
NS_LOG_DEBUG ("Drop packet because RX is already decoding preamble");
NotifyRxDrop (GetAddressedPsduInPpdu (event->GetPpdu ()), BUSY_DECODING_PREAMBLE);
return;
}
m_currentEvent = event;
m_endPreambleDetectionEvents.push_back (Simulator::Schedule (GetPreambleDetectionDuration (), &WifiPhy::StartReceiveHeader, this, event));
}
Ptr<const WifiPsdu>

View File

@@ -65,7 +65,8 @@ enum WifiPhyRxfailureReason
PREAMBLE_DETECTION_PACKET_SWITCH,
FRAME_CAPTURE_PACKET_SWITCH,
OBSS_PD_CCA_RESET,
FILTERED
FILTERED,
HE_TB_PPDU_TOO_LATE
};
/**
@@ -107,6 +108,8 @@ inline std::ostream& operator<< (std::ostream& os, WifiPhyRxfailureReason reason
return (os << "OBSS_PD_CCA_RESET");
case FILTERED:
return (os << "FILTERED");
case HE_TB_PPDU_TOO_LATE:
return (os << "HE_TB_PPDU_TOO_LATE");
case UNKNOWN:
default:
NS_FATAL_ERROR ("Unknown reason");
@@ -1773,6 +1776,11 @@ protected:
virtual void DoInitialize (void);
virtual void DoDispose (void);
/*
* Reset data upon end of TX or RX
*/
void Reset (void);
/**
* The default implementation does nothing and returns true. This method
* is typically called internally by SetChannelNumber ().
@@ -1839,9 +1847,11 @@ protected:
EventId m_endRxEvent; //!< the end of receive event
EventId m_endPhyRxEvent; //!< the end of PHY receive event
EventId m_endPreambleDetectionEvent; //!< the end of preamble detection event
EventId m_endTxEvent; //!< the end of transmit event
std::vector <EventId> m_endPreambleDetectionEvents; //!< the end of preamble detection events
std::map <std::pair<uint64_t /* UID*/, WifiPreamble>, Ptr<Event> > m_currentPreambleEvents; //!< store event associated to a PPDU (that has a unique ID and preamble combination) whose preamble is being received
static uint64_t m_globalPpduUid; //!< Global counter of the PPDU UID

View File

@@ -510,6 +510,12 @@ WifiPpdu::GetUid (void) const
return m_uid;
}
WifiPreamble
WifiPpdu::GetPreamble (void) const
{
return m_preamble;
}
void
WifiPpdu::Print (std::ostream& os) const
{

View File

@@ -132,6 +132,12 @@ public:
*/
uint64_t GetUid (void) const;
/**
* Get the preamble of the PPDU.
* \return the preamble of the PPDU
*/
WifiPreamble GetPreamble (void) const;
/**
* \brief Print the PPDU contents.
* \param os output stream in which the data should be printed.

View File

@@ -97,6 +97,8 @@ protected:
private:
virtual void DoRun (void);
uint64_t m_uid;
};
SpectrumWifiPhyBasicTest::SpectrumWifiPhyBasicTest ()
@@ -107,7 +109,8 @@ SpectrumWifiPhyBasicTest::SpectrumWifiPhyBasicTest ()
SpectrumWifiPhyBasicTest::SpectrumWifiPhyBasicTest (std::string name)
: TestCase (name),
m_count (0)
m_count (0),
m_uid (0)
{
}
@@ -126,7 +129,7 @@ SpectrumWifiPhyBasicTest::MakeSignal (double txPowerWatts)
Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ());
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0);
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
Ptr<SpectrumValue> txPowerSpectrum = WifiSpectrumValueHelper::CreateOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, txPowerWatts, GUARD_WIDTH);
Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters> ();

View File

@@ -102,12 +102,15 @@ private:
* \param expectedFailureCount the number of unsuccessfully received packets
*/
void CheckRxPacketCount (uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
uint64_t m_uid;
};
TestThresholdPreambleDetectionWithoutFrameCapture::TestThresholdPreambleDetectionWithoutFrameCapture ()
: TestCase ("Threshold preamble detection model test when no frame capture model is applied"),
m_countRxSuccess (0),
m_countRxFailure (0)
m_countRxFailure (0),
m_uid (0)
{
}
@@ -125,7 +128,7 @@ TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket (double rxPowerDbm
Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ());
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0);
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
Ptr<SpectrumValue> txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (rxPowerDbm), GUARD_WIDTH);
@@ -289,9 +292,9 @@ TestThresholdPreambleDetectionWithoutFrameCapture::DoRun (void)
Simulator::Schedule (Seconds (5.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, rxPowerDbm);
Simulator::Schedule (Seconds (5.0) + MicroSeconds (2.0), &TestThresholdPreambleDetectionWithoutFrameCapture::SendPacket, this, rxPowerDbm + 3);
// At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to CCA_BUSY
Simulator::Schedule (Seconds (5.0) + NanoSeconds (3999), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
Simulator::Schedule (Seconds (5.0) + NanoSeconds (4000), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::CCA_BUSY);
// At 6us (hence 4us after the last signal is received), no preamble is successfully detected, hence STA PHY STATE should move from IDLE to CCA_BUSY
Simulator::Schedule (Seconds (5.0) + NanoSeconds (5999), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
Simulator::Schedule (Seconds (5.0) + NanoSeconds (6000), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::CCA_BUSY);
// Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2 = 154.8us
Simulator::Schedule (Seconds (5.0) + NanoSeconds (154799), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::CCA_BUSY);
Simulator::Schedule (Seconds (5.0) + NanoSeconds (154800), &TestThresholdPreambleDetectionWithoutFrameCapture::CheckPhyState, this, WifiPhyState::IDLE);
@@ -454,12 +457,15 @@ private:
* \param expectedFailureCount the number of unsuccessfully received packets
*/
void CheckRxPacketCount (uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
uint64_t m_uid;
};
TestThresholdPreambleDetectionWithFrameCapture::TestThresholdPreambleDetectionWithFrameCapture ()
: TestCase ("Threshold preamble detection model test when simple frame capture model is applied"),
m_countRxSuccess (0),
m_countRxFailure (0)
m_countRxSuccess (0),
m_countRxFailure (0),
m_uid (0)
{
}
@@ -477,7 +483,7 @@ TestThresholdPreambleDetectionWithFrameCapture::SendPacket (double rxPowerDbm)
Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ());
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0);
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
Ptr<SpectrumValue> txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (rxPowerDbm), GUARD_WIDTH);
@@ -957,6 +963,8 @@ private:
bool m_rxSuccess1500B; ///< count received packets with 1500B payload
bool m_rxDropped1000B; ///< count dropped packets with 1000B payload
bool m_rxDropped1500B; ///< count dropped packets with 1500B payload
uint64_t m_uid;
};
TestSimpleFrameCaptureModel::TestSimpleFrameCaptureModel ()
@@ -964,7 +972,8 @@ TestSimpleFrameCaptureModel::TestSimpleFrameCaptureModel ()
m_rxSuccess1000B (false),
m_rxSuccess1500B (false),
m_rxDropped1000B (false),
m_rxDropped1500B (false)
m_rxDropped1500B (false),
m_uid (0)
{
}
@@ -982,7 +991,7 @@ TestSimpleFrameCaptureModel::SendPacket (double rxPowerDbm, uint32_t packetSize)
Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ());
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0);
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
Ptr<SpectrumValue> txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (rxPowerDbm), GUARD_WIDTH);
@@ -1165,10 +1174,13 @@ private:
* \param expectedState the expected PHY state
*/
void DoCheckPhyState (WifiPhyState expectedState);
uint64_t m_uid;
};
TestPhyHeadersReception::TestPhyHeadersReception ()
: TestCase ("PHY headers reception test")
: TestCase ("PHY headers reception test"),
m_uid (0)
{
}
@@ -1186,7 +1198,7 @@ TestPhyHeadersReception::SendPacket (double rxPowerDbm)
Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ());
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0);
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
Ptr<SpectrumValue> txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (rxPowerDbm), GUARD_WIDTH);
@@ -1479,6 +1491,8 @@ private:
uint8_t m_rxDroppedBitmapAmpdu1; ///< bitmap of dropped MPDUs in A-MPDU #1
uint8_t m_rxDroppedBitmapAmpdu2; ///< bitmap of dropped MPDUs in A-MPDU #2
uint64_t m_uid; ///< UID
};
TestAmpduReception::TestAmpduReception ()
@@ -1488,7 +1502,8 @@ TestAmpduReception::TestAmpduReception ()
m_rxFailureBitmapAmpdu1 (0),
m_rxFailureBitmapAmpdu2 (0),
m_rxDroppedBitmapAmpdu1 (0),
m_rxDroppedBitmapAmpdu2 (0)
m_rxDroppedBitmapAmpdu2 (0),
m_uid (0)
{
}
@@ -1696,7 +1711,7 @@ TestAmpduReception::SendAmpduWithThreeMpdus (double rxPowerDbm, uint32_t referen
Time txDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand ());
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, 0);
Ptr<WifiPpdu> ppdu = Create<WifiPpdu> (psdu, txVector, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
Ptr<SpectrumValue> txPowerSpectrum = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (FREQUENCY, CHANNEL_WIDTH, DbmToW (rxPowerDbm), GUARD_WIDTH);