mirror of
https://github.com/espressif/openthread.git
synced 2026-06-05 21:14:49 +00:00
[trel] distinguish between user and stack TREL enable requests (#11944)
This change updates the TREL interface enable logic to depend on two requesters: the user (via `otTrelSetEnabled` API or CLI) and the stack (internal, e.g., when the Thread protocol is running). The TREL interface is now considered enabled only when both the user and the stack have requested to enable it. By default, the user preference is 'enabled', allowing the stack to control the state. A key behavior change is that a user's request to disable TREL is now persistent. If the user explicitly disables TREL, it will remain disabled even if the stack stops and restarts (e.g., `ifconfig down` then `ifconfig up`). The user must explicitly re-enable the TREL (calling `otTrelSetEnabled(true)`) to allow TREL to operate again. This is implemented by `Trel::Interface::SetEnabled()` method now taking a `Requester` enum (`kRequesterUser` or `kRequesterStack`) as input and tracking `mUserEnabled` and `mStackEnabled` flags separately. This commit also updates API/CLI documentation and adds a new test (`TestTrelUserDisableRenable`) to verify this new behavior.
This commit is contained in:
committed by
GitHub
parent
2b85b0160f
commit
d27527ce54
@@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (536)
|
||||
#define OPENTHREAD_API_VERSION (537)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -75,17 +75,20 @@ typedef struct otTrelPeer
|
||||
typedef const void *otTrelPeerIterator;
|
||||
|
||||
/**
|
||||
* Enables or disables TREL operation.
|
||||
* Sets the user's preference to enable or disable the TREL operation.
|
||||
*
|
||||
* When @p aEnable is true, this function initiates an ongoing DNS-SD browse on the service name "_trel._udp" within the
|
||||
* local browsing domain to discover other devices supporting TREL. Device also registers a new service to be advertised
|
||||
* using DNS-SD, with the service name is "_trel._udp" indicating its support for TREL. Device is then ready to receive
|
||||
* TREL messages from peers.
|
||||
* The TREL interface's operational state is determined by two factors: the user's preference (set by this function)
|
||||
* and the OpenThread stack's internal state. The TREL interface is enabled only when both the user and the OpenThread
|
||||
* stack have it enabled. Otherwise, it is disabled.
|
||||
*
|
||||
* When @p aEnable is false, this function stops the DNS-SD browse on the service name "_trel._udp", stops advertising
|
||||
* TREL DNS-SD service, and clears the TREL peer table.
|
||||
* Upon OpenThread initialization, the user's preference is set to enabled by default. This allows the stack to
|
||||
* control the TREL interface state automatically (e.g., enabling it when radio links are enabled and disabling
|
||||
* it when radio links are disabled).
|
||||
*
|
||||
* @note By default the OpenThread stack enables the TREL operation on start.
|
||||
* If the user explicitly disables the TREL operation by calling this function with @p aEnable as `false`, it will
|
||||
* remain disabled until the user explicitly re-enables it by calling this function with @p aEnable as `true`. This
|
||||
* ensures the user's 'disable' request persists across other OpenThread stack state changes (which may trigger
|
||||
* disabling/enabling of all radio links, including the TREL link).
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aEnable A boolean to enable/disable the TREL operation.
|
||||
@@ -95,6 +98,9 @@ void otTrelSetEnabled(otInstance *aInstance, bool aEnable);
|
||||
/**
|
||||
* Indicates whether the TREL operation is enabled.
|
||||
*
|
||||
* The TREL operation is enabled if and only if it is enabled by both the user (see `otTrelSetEnabled()`) and the
|
||||
* OpenThread stack.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
*
|
||||
* @retval TRUE if the TREL operation is enabled.
|
||||
|
||||
@@ -4127,6 +4127,8 @@ Indicate whether TREL radio operation is enabled or not.
|
||||
|
||||
`OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE` is required for all `trel` sub-commands.
|
||||
|
||||
The TREL operation is enabled if and only if it is enabled by both the user (see `trel enable`) and the OpenThread stack.
|
||||
|
||||
```bash
|
||||
> trel
|
||||
Enabled
|
||||
@@ -4137,6 +4139,12 @@ Done
|
||||
|
||||
Enable TREL operation.
|
||||
|
||||
The TREL interface's operational state is determined by two factors: the user's preference (set by this command) and the OpenThread stack's internal state. The TREL interface is enabled only when both the user and the OpenThread stack have it enabled. Otherwise, it is disabled.
|
||||
|
||||
Upon OpenThread stack initialization, the user's preference is set to enabled by default. This allows the stack to control the TREL interface state automatically (e.g., enabling it when radio links are enabled and disabling it when radio links are disabled).
|
||||
|
||||
If the user explicitly disables the TREL operation using `trel disable`, it will remain disabled until the user explicitly re-enables it using `trel enable`. This ensures the user's 'disable' request persists across other OpenThread stack state changes (which may trigger disabling/enabling of all radio links, including the TREL link).
|
||||
|
||||
```bash
|
||||
> trel enable
|
||||
Done
|
||||
|
||||
@@ -43,7 +43,7 @@ using namespace ot;
|
||||
|
||||
void otTrelSetEnabled(otInstance *aInstance, bool aEnable)
|
||||
{
|
||||
AsCoreType(aInstance).Get<Trel::Interface>().SetEnabled(aEnable);
|
||||
AsCoreType(aInstance).Get<Trel::Interface>().SetEnabled(aEnable, Trel::Interface::kRequesterUser);
|
||||
}
|
||||
|
||||
bool otTrelIsEnabled(otInstance *aInstance) { return AsCoreType(aInstance).Get<Trel::Interface>().IsEnabled(); }
|
||||
|
||||
@@ -43,64 +43,69 @@ RegisterLogModule("TrelInterface");
|
||||
|
||||
Interface::Interface(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mInitialized(false)
|
||||
, mEnabled(false)
|
||||
, mUserEnabled(true)
|
||||
, mStackEnabled(false)
|
||||
, mFiltered(false)
|
||||
, mState(kStateUninitialized)
|
||||
{
|
||||
}
|
||||
|
||||
void Interface::Init(void)
|
||||
{
|
||||
OT_ASSERT(!mInitialized);
|
||||
|
||||
mInitialized = true;
|
||||
|
||||
if (mEnabled)
|
||||
{
|
||||
mEnabled = false;
|
||||
Enable();
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::SetEnabled(bool aEnable)
|
||||
{
|
||||
if (aEnable)
|
||||
{
|
||||
Enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
Disable();
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::Enable(void)
|
||||
{
|
||||
VerifyOrExit(!mEnabled);
|
||||
|
||||
mEnabled = true;
|
||||
VerifyOrExit(mInitialized);
|
||||
|
||||
otPlatTrelEnable(&GetInstance(), &mUdpPort);
|
||||
Get<PeerDiscoverer>().Start();
|
||||
|
||||
LogInfo("Enabled interface, local port:%u", mUdpPort);
|
||||
VerifyOrExit(mState == kStateUninitialized);
|
||||
mState = kStateDisabled;
|
||||
UpdateState();
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Interface::Disable(void)
|
||||
void Interface::SetEnabled(bool aEnable, Requester aRequester)
|
||||
{
|
||||
VerifyOrExit(mEnabled);
|
||||
switch (aRequester)
|
||||
{
|
||||
case kRequesterUser:
|
||||
VerifyOrExit(mUserEnabled != aEnable);
|
||||
mUserEnabled = aEnable;
|
||||
LogInfo("User %sabled interface", aEnable ? "en" : "dis");
|
||||
break;
|
||||
|
||||
mEnabled = false;
|
||||
VerifyOrExit(mInitialized);
|
||||
case kRequesterStack:
|
||||
VerifyOrExit(mStackEnabled != aEnable);
|
||||
mStackEnabled = aEnable;
|
||||
break;
|
||||
}
|
||||
|
||||
otPlatTrelDisable(&GetInstance());
|
||||
Get<PeerDiscoverer>().Stop();
|
||||
UpdateState();
|
||||
|
||||
LogDebg("Disabled interface");
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Interface::UpdateState(void)
|
||||
{
|
||||
VerifyOrExit(mState != kStateUninitialized);
|
||||
|
||||
if (mUserEnabled && mStackEnabled)
|
||||
{
|
||||
VerifyOrExit(mState == kStateDisabled);
|
||||
mState = kStateEnabled;
|
||||
|
||||
otPlatTrelEnable(&GetInstance(), &mUdpPort);
|
||||
Get<PeerDiscoverer>().Start();
|
||||
|
||||
LogInfo("Enabled interface, local port:%u", mUdpPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(mState == kStateEnabled);
|
||||
mState = kStateDisabled;
|
||||
|
||||
otPlatTrelDisable(&GetInstance());
|
||||
Get<PeerDiscoverer>().Stop();
|
||||
|
||||
LogInfo("Disabled interface");
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
@@ -115,7 +120,7 @@ Error Interface::Send(Packet &aPacket, bool aIsDiscovery)
|
||||
Error error = kErrorNone;
|
||||
Peer *peerEntry;
|
||||
|
||||
VerifyOrExit(mInitialized && mEnabled, error = kErrorAbort);
|
||||
VerifyOrExit(IsEnabled(), error = kErrorAbort);
|
||||
VerifyOrExit(!mFiltered);
|
||||
|
||||
switch (aPacket.GetHeader().GetType())
|
||||
@@ -185,7 +190,7 @@ void Interface::HandleReceived(uint8_t *aBuffer, uint16_t aLength, const Ip6::So
|
||||
{
|
||||
LogDebg("HandleReceived(aLength:%u)", aLength);
|
||||
|
||||
VerifyOrExit(mInitialized && mEnabled && !mFiltered);
|
||||
VerifyOrExit(IsEnabled() && !mFiltered);
|
||||
|
||||
mRxPacket.Init(aBuffer, aLength);
|
||||
Get<Link>().ProcessReceivedPacket(mRxPacket, aSenderAddr);
|
||||
|
||||
@@ -72,37 +72,42 @@ class Interface : public InstanceLocator
|
||||
|
||||
public:
|
||||
/**
|
||||
* Enables or disables the TREL interface.
|
||||
*
|
||||
* @param[in] aEnable A boolean to enable/disable the TREL interface.
|
||||
* Represents an entity requesting to enable or disable the TREL interface (via `SetEnabled()`).
|
||||
*/
|
||||
void SetEnabled(bool aEnable);
|
||||
enum Requester : uint8_t
|
||||
{
|
||||
kRequesterUser, ///< Requested by user (public OT API).
|
||||
kRequesterStack, ///< Requested by stack itself (`Link`).
|
||||
};
|
||||
|
||||
/**
|
||||
* Enables the TREL interface.
|
||||
* Enables or disables the TREL interface by a `Requester`.
|
||||
*
|
||||
* This call initiates an ongoing DNS-SD browse on the service name "_trel._udp" within the local browsing domain
|
||||
* to discover other devices supporting TREL. Device also registers a new service to be advertised using DNS-SD,
|
||||
* with the service name is "_trel._udp" indicating its support for TREL. Device is ready to receive TREL messages
|
||||
* from peers.
|
||||
*/
|
||||
void Enable(void);
|
||||
|
||||
/**
|
||||
* Disables the TREL interface.
|
||||
* The interface is enabled only when it is enabled by both `kRequesterUser` and `kRequesterStack`. Otherwise, it
|
||||
* is disabled.
|
||||
*
|
||||
* This call stops the DNS-SD browse on the service name "_trel._udp", stops advertising TREL DNS-SD service, and
|
||||
* clears the TREL peer table.
|
||||
* Upon OpenThread initialization, the interface state relative to `kRequesterUser` is considered enabled, i.e.,
|
||||
* the stack itself will directly control when to enable/disable the TREL interface (when radio link state changes).
|
||||
*
|
||||
* However, the user can explicitly disable the TREL interface, which can only be re-enabled by the user. This
|
||||
* ensures that if the user disables the TREL interface, it stays disabled regardless of other OpenThread stack
|
||||
* state changes which may trigger disabling/enabling of all radio links, including the TREL link and its interface.
|
||||
*
|
||||
* @param[in] aEnable A boolean to enable/disable the TREL interface.
|
||||
* @param[in] aRequester The requester (user or stack).
|
||||
*/
|
||||
void Disable(void);
|
||||
void SetEnabled(bool aEnable, Requester aRequester);
|
||||
|
||||
/**
|
||||
* Indicates whether the TREL interface is enabled.
|
||||
*
|
||||
* The interface is enabled only when it is enabled by both `kRequesterUser` and `kRequesterStack`. Otherwise, it
|
||||
* is disabled.
|
||||
*
|
||||
* @retval TRUE if the TREL interface is enabled.
|
||||
* @retval FALSE if the TREL interface is disabled.
|
||||
*/
|
||||
bool IsEnabled(void) const { return mEnabled; }
|
||||
bool IsEnabled(void) const { return mState == kStateEnabled; }
|
||||
|
||||
/**
|
||||
* Sets the filter mode (enables/disables filtering).
|
||||
@@ -145,8 +150,17 @@ public:
|
||||
uint16_t GetUdpPort(void) const { return mUdpPort; }
|
||||
|
||||
private:
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStateUninitialized,
|
||||
kStateDisabled,
|
||||
kStateEnabled,
|
||||
};
|
||||
|
||||
explicit Interface(Instance &aInstance);
|
||||
|
||||
void UpdateState(void);
|
||||
|
||||
// Methods used by `Trel::Link`.
|
||||
void Init(void);
|
||||
Error Send(Packet &aPacket, bool aIsDiscovery = false);
|
||||
@@ -154,9 +168,10 @@ private:
|
||||
// Callbacks from `otPlatTrel`.
|
||||
void HandleReceived(uint8_t *aBuffer, uint16_t aLength, const Ip6::SockAddr &aSenderAddr);
|
||||
|
||||
bool mInitialized : 1;
|
||||
bool mEnabled : 1;
|
||||
bool mUserEnabled : 1;
|
||||
bool mStackEnabled : 1;
|
||||
bool mFiltered : 1;
|
||||
State mState;
|
||||
uint16_t mUdpPort;
|
||||
Packet mRxPacket;
|
||||
};
|
||||
|
||||
@@ -72,7 +72,7 @@ void Link::AfterInit(void) { mInterface.Init(); }
|
||||
|
||||
void Link::Enable(void)
|
||||
{
|
||||
mInterface.Enable();
|
||||
mInterface.SetEnabled(true, Interface::kRequesterStack);
|
||||
|
||||
if (mState == kStateDisabled)
|
||||
{
|
||||
@@ -82,7 +82,7 @@ void Link::Enable(void)
|
||||
|
||||
void Link::Disable(void)
|
||||
{
|
||||
mInterface.Disable();
|
||||
mInterface.SetEnabled(false, Interface::kRequesterStack);
|
||||
|
||||
if (mState != kStateDisabled)
|
||||
{
|
||||
|
||||
@@ -167,6 +167,70 @@ void TestTrelBasic(void)
|
||||
}
|
||||
}
|
||||
|
||||
void TestTrelUserDisableReenable(void)
|
||||
{
|
||||
// Validates user disabling of TREL interface persists after
|
||||
// OpenThread state changes such as Thread netif down and up.
|
||||
|
||||
Core nexus;
|
||||
Node &node = nexus.CreateNode();
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("TestTrelUserDisableReenable()");
|
||||
|
||||
nexus.AdvanceTime(0);
|
||||
|
||||
node.GetInstance().SetLogLevel(kLogLevelWarn);
|
||||
SuccessOrQuit(node.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Form network");
|
||||
|
||||
node.Form();
|
||||
nexus.AdvanceTime(13 * 1000);
|
||||
VerifyOrQuit(node.Get<Mle::Mle>().IsLeader());
|
||||
|
||||
VerifyOrQuit(node.Get<ot::Trel::Interface>().IsEnabled());
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Disable TREL interface by `kRequesterUser`");
|
||||
|
||||
node.Get<ot::Trel::Interface>().SetEnabled(false, ot::Trel::Interface::kRequesterUser);
|
||||
VerifyOrQuit(!node.Get<ot::Trel::Interface>().IsEnabled());
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Bring down Thread netif and stop MAC and all radio links");
|
||||
|
||||
node.Get<ThreadNetif>().Down();
|
||||
node.Get<Mac::Mac>().SetEnabled(false);
|
||||
|
||||
VerifyOrQuit(node.Get<Mle::Mle>().IsDisabled());
|
||||
VerifyOrQuit(!node.Get<ot::Trel::Interface>().IsEnabled());
|
||||
|
||||
nexus.AdvanceTime(1000);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Bring up the Thread netif down and restart MLE and Thread operation");
|
||||
|
||||
node.Get<ThreadNetif>().Up();
|
||||
SuccessOrQuit(node.Get<Mle::Mle>().Start());
|
||||
|
||||
nexus.AdvanceTime(60 * 1000);
|
||||
VerifyOrQuit(node.Get<Mle::Mle>().IsLeader());
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Ensure TREL interface remains disabled since it was explicitly disabled by `kRequesterUser`");
|
||||
|
||||
VerifyOrQuit(!node.Get<ot::Trel::Interface>().IsEnabled());
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Enable TREL interface by `kRequesterUser` ");
|
||||
|
||||
node.Get<ot::Trel::Interface>().SetEnabled(true, ot::Trel::Interface::kRequesterUser);
|
||||
|
||||
VerifyOrQuit(node.Get<ot::Trel::Interface>().IsEnabled());
|
||||
}
|
||||
|
||||
void TestTrelDelayedMdnsStartAndPeerRemovalDelay(void)
|
||||
{
|
||||
Core nexus;
|
||||
@@ -252,7 +316,7 @@ void TestTrelDelayedMdnsStartAndPeerRemovalDelay(void)
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Disable TREL Interface (and `PeerDiscoverer`) on `node2`");
|
||||
|
||||
node2.Get<ot::Trel::Interface>().Disable();
|
||||
node2.Get<ot::Trel::Interface>().SetEnabled(false, ot::Trel::Interface::kRequesterUser);
|
||||
nexus.AdvanceTime(2 * 1000);
|
||||
|
||||
VerifyOrQuit(node2.Get<ot::Trel::PeerTable>().GetNumberOfPeers() == 0);
|
||||
@@ -275,7 +339,7 @@ void TestTrelDelayedMdnsStartAndPeerRemovalDelay(void)
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Re-enable TREL Interface (and `PeerDiscoverer`) on `node2`");
|
||||
|
||||
node2.Get<ot::Trel::Interface>().Enable();
|
||||
node2.Get<ot::Trel::Interface>().SetEnabled(true, ot::Trel::Interface::kRequesterUser);
|
||||
nexus.AdvanceTime(15 * 1000);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -329,7 +393,7 @@ void TestTrelDelayedMdnsStartAndPeerRemovalDelay(void)
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Disable TREL Interface (and `PeerDiscoverer`) on `node2` again and signal its removal on mDNS");
|
||||
|
||||
node2.Get<ot::Trel::Interface>().Disable();
|
||||
node2.Get<ot::Trel::Interface>().SetEnabled(false, ot::Trel::Interface::kRequesterUser);
|
||||
VerifyOrQuit(node2.Get<ot::Trel::PeerTable>().IsEmpty());
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -388,7 +452,7 @@ void TestServiceNameConflict(void)
|
||||
|
||||
Log("Disable TREL interface but enable mDNS on `conflictNode`");
|
||||
|
||||
conflictNode.Get<ot::Trel::Interface>().Disable();
|
||||
conflictNode.Get<ot::Trel::Interface>().SetEnabled(false, ot::Trel::Interface::kRequesterUser);
|
||||
SuccessOrQuit(conflictNode.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
|
||||
|
||||
Log("Register a service on `conflictNode` with same name that `node1` would use");
|
||||
@@ -472,7 +536,7 @@ void TestHostAddressChange(void)
|
||||
|
||||
Log("Disable TREL interface but enable mDNS on `node2`");
|
||||
|
||||
node2.Get<ot::Trel::Interface>().Disable();
|
||||
node2.Get<ot::Trel::Interface>().SetEnabled(false, ot::Trel::Interface::kRequesterUser);
|
||||
SuccessOrQuit(node2.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
|
||||
|
||||
Log("Manually register a TREL service on `node2` with proper TXT data");
|
||||
@@ -609,7 +673,7 @@ void TestMultiServiceSameHost(void)
|
||||
|
||||
Log("Disable TREL interface but enable mDNS on `multiServiceNode`");
|
||||
|
||||
multiServiceNode.Get<ot::Trel::Interface>().Disable();
|
||||
multiServiceNode.Get<ot::Trel::Interface>().SetEnabled(false, ot::Trel::Interface::kRequesterUser);
|
||||
SuccessOrQuit(multiServiceNode.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
|
||||
|
||||
Log("Manually register three TREL services on the `multiServiceNode`");
|
||||
@@ -800,6 +864,7 @@ int main(void)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
ot::Nexus::TestTrelBasic();
|
||||
ot::Nexus::TestTrelUserDisableReenable();
|
||||
ot::Nexus::TestTrelDelayedMdnsStartAndPeerRemovalDelay();
|
||||
ot::Nexus::TestServiceNameConflict();
|
||||
ot::Nexus::TestHostAddressChange();
|
||||
|
||||
Reference in New Issue
Block a user