185 lines
8.2 KiB
C++
185 lines
8.2 KiB
C++
/*
|
|
* Copyright (c) 2024 Universita' di Napoli Federico II
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-only
|
|
*
|
|
* Author: Stefano Avallone <stavallo@unina.it>
|
|
*/
|
|
|
|
#ifndef ADVANCED_EMLSR_MANAGER_H
|
|
#define ADVANCED_EMLSR_MANAGER_H
|
|
|
|
#include "default-emlsr-manager.h"
|
|
|
|
#include "ns3/channel-access-manager.h"
|
|
|
|
#include <memory>
|
|
|
|
namespace ns3
|
|
{
|
|
|
|
class WifiPhyListener;
|
|
|
|
/**
|
|
* @ingroup wifi
|
|
*
|
|
* AdvancedEmlsrManager is an advanced EMLSR manager.
|
|
*/
|
|
class AdvancedEmlsrManager : public DefaultEmlsrManager
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Get the type ID.
|
|
* @return the object TypeId
|
|
*/
|
|
static TypeId GetTypeId();
|
|
|
|
AdvancedEmlsrManager();
|
|
~AdvancedEmlsrManager() override;
|
|
|
|
std::optional<WifiIcfDrop> CheckMainPhyTakesOverDlTxop(uint8_t linkId) const override;
|
|
|
|
/**
|
|
* This method is called by the PHY listener attached to the main PHY when a switch main PHY
|
|
* back timer is started to notify of events that may delay the channel access for the main
|
|
* PHY on the current link. If the expected channel access is beyond the end of the switch
|
|
* main PHY timer expiration plus a channel switch delay, the timer is stopped immediately.
|
|
*/
|
|
void InterruptSwitchMainPhyBackTimerIfNeeded();
|
|
|
|
protected:
|
|
void DoDispose() override;
|
|
void DoSetWifiMac(Ptr<StaWifiMac> mac) override;
|
|
std::pair<bool, Time> DoGetDelayUntilAccessRequest(uint8_t linkId) override;
|
|
std::pair<bool, Time> GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) override;
|
|
void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId, AcIndex aci) override;
|
|
void NotifyEmlsrModeChanged() 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);
|
|
|
|
/**
|
|
* Use information from NAV and CCA performed by the given PHY on the given link in the last
|
|
* PIFS interval to determine whether the given EDCAF can start a TXOP. This function is
|
|
* intended to be used when the main PHY switches channel to start an UL TXOP on a link where
|
|
* channel access was obtained by a non-TX capable aux PHY.
|
|
*
|
|
* @param phy the PHY that performed CCA in the last PIFS interval
|
|
* @param linkId the ID of the given link
|
|
* @param edca the given EDCAF
|
|
*/
|
|
void CheckNavAndCcaLastPifs(Ptr<WifiPhy> phy, uint8_t linkId, Ptr<QosTxop> edca);
|
|
|
|
/**
|
|
* Determine whether the main PHY shall be requested to switch to the link of an aux PHY that
|
|
* is expected to gain channel access through the given AC in the given delay but it is not
|
|
* TX capable.
|
|
*
|
|
* @param linkId the ID of the link on which the aux PHY is operating
|
|
* @param aci the index of the given AC
|
|
* @param delay the delay after which the given AC is expected to gain channel access. Zero
|
|
* indicates that channel access has been actually gained
|
|
* @return whether the main PHY shall be requested to switch to the link of the aux PHY
|
|
*/
|
|
bool RequestMainPhyToSwitch(uint8_t linkId, AcIndex aci, const Time& delay);
|
|
|
|
/**
|
|
* This method is called when the given AC of the EMLSR client is expected to get channel
|
|
* access in the given delay on the given link, on which an aux PHY that is not TX capable
|
|
* is operating. This method has to decide whether to request the main PHY to switch to the
|
|
* given link to try to start a TXOP.
|
|
*
|
|
* @param linkId the ID of the given link
|
|
* @param aci the index of the given AC
|
|
* @param delay the delay after which the given AC is expected to gain channel access
|
|
*/
|
|
void SwitchMainPhyIfTxopToBeGainedByAuxPhy(uint8_t linkId, AcIndex aci, const Time& delay);
|
|
|
|
/**
|
|
* This method is called when the switch main PHY back timer (which is started when the main PHY
|
|
* switches to the link of an aux PHY that does not switch and is not TX capable) expires and
|
|
* decides whether to delay the request to switch the main PHY back to the preferred link or to
|
|
* execute it immediately. This method can also be called to terminate a running switch main PHY
|
|
* back timer, in case it is determined that channel access is not expected to be gained before
|
|
* the expiration of the timer plus the channel switch delay.
|
|
*
|
|
* @param linkId the ID of the link that the main PHY is leaving
|
|
* @param stopReason the reason for terminating the switch main PHY back timer before expiration
|
|
*/
|
|
void SwitchMainPhyBackDelayExpired(uint8_t linkId,
|
|
std::optional<WifiExpectedAccessReason> stopReason);
|
|
|
|
private:
|
|
void DoNotifyTxopEnd(uint8_t linkId) override;
|
|
void DoNotifyIcfReceived(uint8_t linkId) override;
|
|
void DoNotifyUlTxopStart(uint8_t linkId) override;
|
|
|
|
bool m_allowUlTxopInRx; //!< whether a (main or aux) PHY is allowed to start an UL
|
|
//!< TXOP if another PHY is receiving a PPDU
|
|
bool m_interruptSwitching; //!< whether a main PHY switching can be interrupted to start
|
|
//!< switching to another link
|
|
bool m_useAuxPhyCca; //!< whether the CCA performed in the last PIFS interval by a
|
|
//!< non-TX capable aux PHY should be used when the main PHY
|
|
//!< ends switching to the aux PHY's link to determine whether
|
|
//!< TX can start or not
|
|
Time m_switchMainPhyBackDelay; //!< duration of the timer started in case of non-TX capable aux
|
|
//!< PHY when medium is sensed busy during the PIFS interval
|
|
//!< preceding/following the main PHY switch end
|
|
EventId m_ccaLastPifs; //!< event scheduled in case of non-TX capable aux PHY to
|
|
//!< determine whether TX can be started based on whether
|
|
//!< the medium has been idle during the last PIFS interval
|
|
EventId m_switchMainPhyBackEvent; //!< event scheduled in case of non-TX capable aux PHY when
|
|
//!< medium is sensed busy during the PIFS interval
|
|
//!< preceding/following the main PHY switch end
|
|
std::shared_ptr<WifiPhyListener>
|
|
m_phyListener; //!< PHY listener connected to the main PHY while operating on the link of
|
|
//!< an aux PHY that is not TX capable
|
|
};
|
|
|
|
/**
|
|
* Struct to trace that main PHY switched to leave a link on which an aux PHY was expected to gain
|
|
* a TXOP but the main PHY did not manage to gain a TXOP in the pre-configured amount of time.
|
|
*/
|
|
struct EmlsrSwitchMainPhyBackTrace : public EmlsrMainPhySwitchTraceImpl<EmlsrSwitchMainPhyBackTrace>
|
|
{
|
|
static constexpr std::string_view m_name = "TxopNotGainedOnAuxPhyLink"; //!< trace name
|
|
|
|
Time elapsed; //!< the time elapsed since the switch main PHY back timer started
|
|
std::optional<WifiExpectedAccessReason>
|
|
earlySwitchReason; //!< the reason why the main PHY switches back before the expiration of
|
|
//!< the switch main PHY back timer
|
|
bool isSwitching; //!< whether the main PHY is switching while it is requested to switch back
|
|
|
|
/**
|
|
* Constructor provided because this struct is not an aggregate (it has a base struct), hence
|
|
* we cannot use designated initializers.
|
|
*
|
|
* @param time the value for the elapsed field
|
|
* @param reason the value for the earlySwitchReason field
|
|
* @param switching the value for the isSwitching field
|
|
*/
|
|
EmlsrSwitchMainPhyBackTrace(Time time,
|
|
std::optional<WifiExpectedAccessReason> reason,
|
|
bool switching)
|
|
: elapsed(time),
|
|
earlySwitchReason(reason),
|
|
isSwitching(switching)
|
|
{
|
|
}
|
|
};
|
|
|
|
} // namespace ns3
|
|
|
|
#endif /* ADVANCED_EMLSR_MANAGER_H */
|