wifi: EMLSR client switches to listening mode as soon as it is notified of the MAC header of an MPDU that is not addressed to it
This commit is contained in:
@@ -67,6 +67,32 @@ AdvancedEmlsrManager::~AdvancedEmlsrManager()
|
||||
NS_LOG_FUNCTION_NOARGS();
|
||||
}
|
||||
|
||||
void
|
||||
AdvancedEmlsrManager::DoDispose()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
for (auto phy : GetStaMac()->GetDevice()->GetPhys())
|
||||
{
|
||||
phy->TraceDisconnectWithoutContext(
|
||||
"PhyRxMacHeaderEnd",
|
||||
MakeCallback(&AdvancedEmlsrManager::ReceivedMacHdr, this).Bind(phy));
|
||||
}
|
||||
DefaultEmlsrManager::DoDispose();
|
||||
}
|
||||
|
||||
void
|
||||
AdvancedEmlsrManager::DoSetWifiMac(Ptr<StaWifiMac> mac)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << mac);
|
||||
|
||||
for (auto phy : GetStaMac()->GetDevice()->GetPhys())
|
||||
{
|
||||
phy->TraceConnectWithoutContext(
|
||||
"PhyRxMacHeaderEnd",
|
||||
MakeCallback(&AdvancedEmlsrManager::ReceivedMacHdr, this).Bind(phy));
|
||||
}
|
||||
}
|
||||
|
||||
Time
|
||||
AdvancedEmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId)
|
||||
{
|
||||
@@ -162,4 +188,36 @@ AdvancedEmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId)
|
||||
return Time{0};
|
||||
}
|
||||
|
||||
void
|
||||
AdvancedEmlsrManager::ReceivedMacHdr(Ptr<WifiPhy> phy,
|
||||
const WifiMacHeader& macHdr,
|
||||
const WifiTxVector& txVector,
|
||||
Time psduDuration)
|
||||
{
|
||||
auto linkId = GetStaMac()->GetLinkForPhy(phy);
|
||||
if (!linkId.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
NS_LOG_FUNCTION(this << *linkId << macHdr << txVector << psduDuration.As(Time::MS));
|
||||
|
||||
auto& ongoingTxopEnd = GetEhtFem(*linkId)->GetOngoingTxopEndEvent();
|
||||
|
||||
if (m_useNotifiedMacHdr && ongoingTxopEnd.IsPending() &&
|
||||
macHdr.GetAddr1() != GetEhtFem(*linkId)->GetAddress() && !macHdr.GetAddr1().IsBroadcast() &&
|
||||
!(macHdr.IsCts() && macHdr.GetAddr1() == GetEhtFem(*linkId)->GetBssid() /* CTS-to-self */))
|
||||
{
|
||||
// the EMLSR client is no longer involved in the TXOP and switching to listening mode
|
||||
ongoingTxopEnd.Cancel();
|
||||
// this method is a callback connected to the PhyRxMacHeaderEnd trace source of WifiPhy
|
||||
// and is called within a for loop that executes all the callbacks. The call to NotifyTxop
|
||||
// below leads the main PHY to be connected back to the primary link, thus
|
||||
// the ResetPhy() method of the FEM on the non-primary link is called, which disconnects
|
||||
// another callback (FEM::ReceivedMacHdr) from the PhyRxMacHeaderEnd trace source of
|
||||
// the main PHY, thus invalidating the list of callbacks on which the for loop iterates.
|
||||
// Hence, schedule the call to NotifyTxopEnd to execute it outside such for loop.
|
||||
Simulator::ScheduleNow(&AdvancedEmlsrManager::NotifyTxopEnd, this, *linkId, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -44,6 +44,24 @@ class AdvancedEmlsrManager : public DefaultEmlsrManager
|
||||
|
||||
Time GetDelayUntilAccessRequest(uint8_t linkId) override;
|
||||
|
||||
protected:
|
||||
void DoDispose() override;
|
||||
void DoSetWifiMac(Ptr<StaWifiMac> mac) override;
|
||||
|
||||
/**
|
||||
* Possibly take actions when notified of the MAC header of the MPDU being received by the
|
||||
* given PHY.
|
||||
*
|
||||
* \param phy the given PHY
|
||||
* \param macHdr the MAC header of the MPDU being received
|
||||
* \param txVector the TXVECTOR used to transmit the PSDU
|
||||
* \param psduDuration the remaining duration of the PSDU
|
||||
*/
|
||||
void ReceivedMacHdr(Ptr<WifiPhy> phy,
|
||||
const WifiMacHeader& macHdr,
|
||||
const WifiTxVector& txVector,
|
||||
Time psduDuration);
|
||||
|
||||
private:
|
||||
bool m_useNotifiedMacHdr; //!< whether to use the information about the MAC header of
|
||||
//!< the MPDU being received (if notified by the PHY)
|
||||
|
||||
@@ -1163,6 +1163,12 @@ EhtFrameExchangeManager::CheckEmlsrClientStartingTxop(const WifiMacHeader& hdr,
|
||||
return true;
|
||||
}
|
||||
|
||||
EventId&
|
||||
EhtFrameExchangeManager::GetOngoingTxopEndEvent()
|
||||
{
|
||||
return m_ongoingTxopEnd;
|
||||
}
|
||||
|
||||
void
|
||||
EhtFrameExchangeManager::PsduRxError(Ptr<const WifiPsdu> psdu)
|
||||
{
|
||||
|
||||
@@ -126,6 +126,12 @@ class EhtFrameExchangeManager : public HeFrameExchangeManager
|
||||
*/
|
||||
void EmlsrSwitchToListening(const Mac48Address& address, const Time& delay);
|
||||
|
||||
/**
|
||||
* \return a reference to the event indicating the possible end of the current TXOP (of
|
||||
* which this device is not the holder)
|
||||
*/
|
||||
EventId& GetOngoingTxopEndEvent();
|
||||
|
||||
protected:
|
||||
void DoDispose() override;
|
||||
void RxStartIndication(WifiTxVector txVector, Time psduDuration) override;
|
||||
|
||||
@@ -177,6 +177,13 @@ EmlsrManager::SetWifiMac(Ptr<StaWifiMac> mac)
|
||||
m_staMac->TraceConnectWithoutContext("AckedMpdu", MakeCallback(&EmlsrManager::TxOk, this));
|
||||
m_staMac->TraceConnectWithoutContext("DroppedMpdu",
|
||||
MakeCallback(&EmlsrManager::TxDropped, this));
|
||||
DoSetWifiMac(mac);
|
||||
}
|
||||
|
||||
void
|
||||
EmlsrManager::DoSetWifiMac(Ptr<StaWifiMac> mac)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << mac);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -280,6 +280,13 @@ class EmlsrManager : public Object
|
||||
protected:
|
||||
void DoDispose() override;
|
||||
|
||||
/**
|
||||
* Allow subclasses to take actions when the MAC is set.
|
||||
*
|
||||
* \param mac the wifi MAC
|
||||
*/
|
||||
virtual void DoSetWifiMac(Ptr<StaWifiMac> mac);
|
||||
|
||||
/**
|
||||
* \return the MAC of the non-AP MLD managed by this EMLSR Manager.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user