Skip to content

Commit

Permalink
wifi: Pass the TXOP holder to EHT FEM TxopEnd()
Browse files Browse the repository at this point in the history
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
  • Loading branch information
stavallo authored and Stefano Avallone committed May 6, 2024
1 parent 2333d49 commit cb308bd
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 28 deletions.
32 changes: 19 additions & 13 deletions src/wifi/model/eht/eht-frame-exchange-manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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());
}
}

Expand All @@ -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())
{
Expand All @@ -1028,19 +1030,19 @@ 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;
}

if (m_staMac && m_staMac->IsEmlsrLink(m_linkId))
{
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));
}
}

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -1123,15 +1128,16 @@ 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;
}

// we may send a response after a SIFS or we may receive another frame after a SIFS.
// 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
4 changes: 3 additions & 1 deletion src/wifi/model/eht/eht-frame-exchange-manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
28 changes: 14 additions & 14 deletions src/wifi/test/wifi-emlsr-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1483,30 +1483,30 @@ 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);
NS_TEST_ASSERT_MSG_EQ(linkIdOpt.has_value(),
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,
Expand Down

0 comments on commit cb308bd

Please sign in to comment.