wifi: Correctly compute the time to RX end to be passed to WifiPhyStateHelper::SwitchToRx()

This commit is contained in:
Stefano Avallone
2022-06-17 00:41:41 +02:00
parent c423249242
commit 18f8b488d3
5 changed files with 58 additions and 44 deletions

View File

@@ -677,48 +677,64 @@ HePhy::IsConfigSupported (Ptr<const WifiPpdu> ppdu) const
return true;
}
void
Time
HePhy::DoStartReceivePayload (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
const WifiTxVector& txVector = event->GetTxVector ();
Ptr<const WifiPpdu> ppdu = event->GetPpdu ();
if (txVector.IsUlMu ())
if (!txVector.IsUlMu ())
{
NS_ASSERT (txVector.GetModulationClass () == WIFI_MOD_CLASS_HE);
bool isAp = (DynamicCast<ApWifiMac> (m_wifiPhy->GetDevice ()->GetMac ()) != 0);
if (!isAp)
return PhyEntity::DoStartReceivePayload (event);
}
NS_ASSERT (txVector.GetModulationClass () == WIFI_MOD_CLASS_HE);
// TX duration is determined by the Length field of TXVECTOR
Time payloadDuration = ConvertLSigLengthToHeTbPpduDuration (txVector.GetLength (),
txVector,
m_wifiPhy->GetPhyBand ())
- CalculatePhyPreambleAndHeaderDuration (txVector);
// This method is called when we start receiving the first OFDMA payload. To
// compute the time to the reception end of the last TB PPDU, we need to add the
// offset of the last TB PPDU to the payload duration (same for all TB PPDUs)
Time maxOffset {0};
for (const auto& beginOfdmaPayloadRxEvent : m_beginOfdmaPayloadRxEvents)
{
maxOffset = Max (maxOffset, Simulator::GetDelayLeft (beginOfdmaPayloadRxEvent.second));
}
Time timeToEndRx = payloadDuration + maxOffset;
bool isAp = (DynamicCast<ApWifiMac> (m_wifiPhy->GetDevice ()->GetMac ()) != 0);
if (!isAp)
{
NS_LOG_DEBUG ("Ignore HE TB PPDU payload received by STA but keep state in Rx");
NotifyPayloadBegin (txVector, timeToEndRx);
m_endRxPayloadEvents.push_back (Simulator::Schedule (timeToEndRx,
&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)
{
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> ()});
//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 ());
}
beginOfdmaPayloadRxEvent.second.Cancel ();
}
m_beginOfdmaPayloadRxEvents.clear ();
}
else
{
PhyEntity::DoStartReceivePayload (event);
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> ()});
//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 ());
}
}
return timeToEndRx;
}
void

View File

@@ -386,7 +386,7 @@ protected:
PhyFieldRxStatus ProcessSigB (Ptr<Event> event, PhyFieldRxStatus status) override;
Ptr<Event> DoGetEvent (Ptr<const WifiPpdu> ppdu, RxPowerWattPerChannelBand& rxPowersW) override;
bool IsConfigSupported (Ptr<const WifiPpdu> ppdu) const override;
void DoStartReceivePayload (Ptr<Event> event) override;
Time DoStartReceivePayload (Ptr<Event> event) override;
std::pair<uint16_t, WifiSpectrumBand> GetChannelWidthAndBand (const WifiTxVector& txVector, uint16_t staId) const override;
void RxPayloadSucceeded (Ptr<const WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
const WifiTxVector& txVector, uint16_t staId,

View File

@@ -529,17 +529,12 @@ PhyEntity::StartReceivePayload (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
NS_ASSERT (m_wifiPhy->m_endPhyRxEvent.IsExpired ());
const 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)
Time payloadDuration = DoStartReceivePayload (event);
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
Time
PhyEntity::DoStartReceivePayload (Ptr<Event> event)
{
NS_LOG_FUNCTION (this << *event);
@@ -549,8 +544,12 @@ PhyEntity::DoStartReceivePayload (Ptr<Event> event)
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 ()),
const WifiTxVector& txVector = event->GetTxVector ();
Time payloadDuration = ppdu->GetTxDuration () - CalculatePhyPreambleAndHeaderDuration (txVector);
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
m_endRxPayloadEvents.push_back (Simulator::Schedule (payloadDuration,
&PhyEntity::EndReceivePayload, this, event));
return payloadDuration;
}
void

View File

@@ -560,8 +560,9 @@ protected:
* and perform amendment-specific actions.
*
* \param event the event holding incoming PPDU's information
* \return the payload duration
*/
virtual void DoStartReceivePayload (Ptr<Event> event);
virtual Time DoStartReceivePayload (Ptr<Event> event);
/**
* Perform amendment-specific actions before resetting PHY at

View File

@@ -502,8 +502,7 @@ void
WifiPhyStateHelper::SwitchFromRxEndOk (void)
{
NS_LOG_FUNCTION (this);
NS_ASSERT (Abs (m_endRx - Simulator::Now ()) < MicroSeconds (1)); //1us corresponds to the maximum propagation delay (delay spread)
//TODO: a better fix would be to call the function once all HE TB PPDUs are received
NS_ASSERT (m_endRx == Simulator::Now ());
NotifyRxEndOk ();
DoSwitchFromRx ();
}
@@ -512,8 +511,7 @@ void
WifiPhyStateHelper::SwitchFromRxEndError (void)
{
NS_LOG_FUNCTION (this);
NS_ASSERT (Abs (m_endRx - Simulator::Now ()) < MicroSeconds (1)); //1us corresponds to the maximum propagation delay (delay spread)
//TODO: a better fix would be to call the function once all HE TB PPDUs are received
NS_ASSERT (m_endRx == Simulator::Now ());
NotifyRxEndError ();
DoSwitchFromRx ();
}