wifi: Pass the TXOP holder to EHT FEM TxopEnd()

because TxopEnd() may be called when the TXOP holder has been already
reset, e.g., when a TXOP is terminated with a CF-End frame
This commit is contained in:
Stefano Avallone
2024-01-12 12:06:54 +01:00
committed by Stefano Avallone
parent 2333d491b6
commit cb308bd3dd
3 changed files with 36 additions and 28 deletions

View File

@@ -840,7 +840,8 @@ EhtFrameExchangeManager::PostProcessFrame(Ptr<const WifiPsdu> psdu, const WifiTx
auto delay =
m_phy->GetSifs() + m_phy->GetSlot() + MicroSeconds(RX_PHY_START_DELAY_USEC);
NS_LOG_DEBUG("Expected TXOP end=" << (Simulator::Now() + delay).As(Time::S));
m_ongoingTxopEnd = Simulator::Schedule(delay, &EhtFrameExchangeManager::TxopEnd, this);
m_ongoingTxopEnd =
Simulator::Schedule(delay, &EhtFrameExchangeManager::TxopEnd, this, m_txopHolder);
}
else
{
@@ -991,7 +992,8 @@ EhtFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
NS_LOG_DEBUG("Expected TXOP end=" << (Simulator::Now() + m_phy->GetSifs()).As(Time::S));
m_ongoingTxopEnd = Simulator::Schedule(m_phy->GetSifs() + NanoSeconds(1),
&EhtFrameExchangeManager::TxopEnd,
this);
this,
hdr.GetAddr2());
}
}
@@ -1015,9 +1017,9 @@ EhtFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
}
void
EhtFrameExchangeManager::TxopEnd()
EhtFrameExchangeManager::TxopEnd(const std::optional<Mac48Address>& txopHolder)
{
NS_LOG_FUNCTION(this);
NS_LOG_FUNCTION(this << txopHolder.has_value());
if (m_phy->IsReceivingPhyHeader())
{
@@ -1028,7 +1030,8 @@ EhtFrameExchangeManager::TxopEnd()
NS_LOG_DEBUG("PHY is decoding the PHY header of PPDU, postpone TXOP end");
m_ongoingTxopEnd = Simulator::Schedule(MicroSeconds(WAIT_FOR_RXSTART_DELAY_USEC),
&EhtFrameExchangeManager::TxopEnd,
this);
this,
txopHolder);
return;
}
@@ -1036,11 +1039,10 @@ EhtFrameExchangeManager::TxopEnd()
{
m_staMac->GetEmlsrManager()->NotifyTxopEnd(m_linkId);
}
else if (m_apMac && m_txopHolder &&
GetWifiRemoteStationManager()->GetEmlsrEnabled(*m_txopHolder))
else if (m_apMac && txopHolder && GetWifiRemoteStationManager()->GetEmlsrEnabled(*txopHolder))
{
// EMLSR client terminated its TXOP and is back to listening operation
EmlsrSwitchToListening(*m_txopHolder, Seconds(0));
EmlsrSwitchToListening(*txopHolder, Seconds(0));
}
}
@@ -1083,7 +1085,8 @@ EhtFrameExchangeManager::UpdateTxopEndOnTxStart(Time txDuration, Time durationId
}
NS_LOG_DEBUG("Expected TXOP end=" << (Simulator::Now() + delay).As(Time::S));
m_ongoingTxopEnd = Simulator::Schedule(delay, &EhtFrameExchangeManager::TxopEnd, this);
m_ongoingTxopEnd =
Simulator::Schedule(delay, &EhtFrameExchangeManager::TxopEnd, this, m_txopHolder);
}
void
@@ -1101,8 +1104,10 @@ EhtFrameExchangeManager::UpdateTxopEndOnRxStartIndication(Time psduDuration)
m_ongoingTxopEnd.Cancel();
NS_LOG_DEBUG("Expected TXOP end=" << (Simulator::Now() + psduDuration).As(Time::S));
m_ongoingTxopEnd =
Simulator::Schedule(psduDuration + NanoSeconds(1), &EhtFrameExchangeManager::TxopEnd, this);
m_ongoingTxopEnd = Simulator::Schedule(psduDuration + NanoSeconds(1),
&EhtFrameExchangeManager::TxopEnd,
this,
m_txopHolder);
}
void
@@ -1123,7 +1128,7 @@ EhtFrameExchangeManager::UpdateTxopEndOnRxEnd(Time durationId)
if (durationId <= m_phy->GetSifs())
{
NS_LOG_DEBUG("Assume TXOP ended based on Duration/ID value");
TxopEnd();
TxopEnd(m_txopHolder);
return;
}
@@ -1131,7 +1136,8 @@ EhtFrameExchangeManager::UpdateTxopEndOnRxEnd(Time durationId)
// Postpone the TXOP end by considering the latter (which takes longer)
auto delay = m_phy->GetSifs() + m_phy->GetSlot() + MicroSeconds(RX_PHY_START_DELAY_USEC);
NS_LOG_DEBUG("Expected TXOP end=" << (Simulator::Now() + delay).As(Time::S));
m_ongoingTxopEnd = Simulator::Schedule(delay, &EhtFrameExchangeManager::TxopEnd, this);
m_ongoingTxopEnd =
Simulator::Schedule(delay, &EhtFrameExchangeManager::TxopEnd, this, m_txopHolder);
}
} // namespace ns3

View File

@@ -156,8 +156,10 @@ class EhtFrameExchangeManager : public HeFrameExchangeManager
/**
* Take actions when a TXOP (of which we are not the holder) ends.
*
* \param txopHolder the holder of the TXOP (if any)
*/
void TxopEnd();
void TxopEnd(const std::optional<Mac48Address>& txopHolder);
EventId m_ongoingTxopEnd; //!< event indicating the possible end of the current TXOP (of which
//!< we are not the holder)

View File

@@ -1483,12 +1483,13 @@ EmlsrDlTxopTest::CheckResults()
*/
// for each EMLSR client, there should be a frame exchange with ICF and no data frame
// (ICF protects the EML Notification response) and two frame exchanges with data frames
// (ICF protects the EML Notification response) if the EML Notification response is sent
// while EMLSR mode is still enabled and two frame exchanges with data frames
for (std::size_t i = 0; i < m_nEmlsrStations; i++)
{
// the default EMLSR Manager requests to send EML Notification frames on the link where
// the main PHY is operating, hence this link is an EMLSR link and the EML Notification
// frame is protected by an ICF
// the main PHY is operating; if EMLSR mode is still enabled on this link when the AP MLD
// sends the EML Notification response, the latter is protected by an ICF
auto exchangeIt = frameExchanges.at(i).cbegin();
auto linkIdOpt = m_staMacs[i]->GetLinkForPhy(m_mainPhyId);
@@ -1496,17 +1497,16 @@ EmlsrDlTxopTest::CheckResults()
true,
"Didn't find a link on which the main PHY is operating");
NS_TEST_EXPECT_MSG_EQ(IsTrigger(exchangeIt->front()->psduMap),
true,
"Expected an MU-RTS TF as ICF of first frame exchange sequence");
NS_TEST_EXPECT_MSG_EQ(+exchangeIt->front()->linkId,
+linkIdOpt.value(),
"ICF was not sent on the expected link");
NS_TEST_EXPECT_MSG_EQ(exchangeIt->size(),
1,
"Expected no data frame in the first frame exchange sequence");
frameExchanges.at(i).pop_front();
if (IsTrigger(exchangeIt->front()->psduMap))
{
NS_TEST_EXPECT_MSG_EQ(+exchangeIt->front()->linkId,
+linkIdOpt.value(),
"ICF was not sent on the expected link");
NS_TEST_EXPECT_MSG_EQ(exchangeIt->size(),
1,
"Expected no data frame in the first frame exchange sequence");
frameExchanges.at(i).pop_front();
}
NS_TEST_EXPECT_MSG_GT_OR_EQ(frameExchanges.at(i).size(),
2,