[dataset] remove legacy wake-up channel from operational dataset (#13614)

The wake-up channel TLV was originally introduced into OpenThread as part
of early experimental prototyping for wake-up / peer-to-peer features
before the design was finalized in the Thread Group. Unfortunately, it
was added directly to the public Operational Dataset structures and
MeshCoP definitions without any compile-time feature flags or build
guards, exposing it as standard dataset API.

The finalized Thread Direct specification has significantly evolved and
no longer utilizes a network-wide wake-up channel in the Operational
Dataset. As a result, retaining wake-up channel support in the dataset is
obsolete, non-compliant with the spec, and can lead to confusion when
configuring Thread networks.

This commit removes the legacy wake-up channel from the Operational
Dataset across public APIs, core modules, CLI, and tooling:

- Public API (`include/openthread/dataset.h`):
  - Removes `mIsWakeupChannelPresent` from `otOperationalDatasetComponents`.
  - Removes `mWakeupChannel` from `otOperationalDataset`.
  - Removes `OT_MESHCOP_TLV_WAKEUP_CHANNEL` from `otMeshcopTlvType`.

- Core MeshCoP & MLE (`src/core/`):
  - Removes `kWakeupChannel` from `MeshCoP::Dataset` components, types,
    and TLV definitions (`meshcop_tlvs.hpp`).
  - Removes `WakeupChannelTlv` handling and default generation from
    `ActiveDatasetManager` (`dataset_manager_ftd.cpp`).
  - Removes `kWakeupChannel` from `Mle::Tlv::Type` (`mle_tlvs.hpp`).

- CLI and Tooling:
  - Removes `dataset wakeupchannel` CLI command and its documentation
    (`cli_dataset.cpp`, `cli_dataset.hpp`, `README_DATASET.md`).
  - Cleans up `dataset wakeupchannel` parsing and buffer helpers in the
    OTCI Python utility (`tools/otci/otci/otci.py`).
  - Removes `WakeupChannel` entry and TLV type from the TCAT BLE client
    (`tools/tcat_ble_client/`).
This commit is contained in:
Abtin Keshavarzian
2026-09-22 08:30:04 -07:00
committed by GitHub
parent c71f802c39
commit 0a2cad1e65
14 changed files with 4 additions and 142 deletions
-3
View File
@@ -207,7 +207,6 @@ typedef struct otOperationalDatasetComponents
bool mIsPskcPresent; ///< TRUE if PSKc is present, FALSE otherwise.
bool mIsSecurityPolicyPresent; ///< TRUE if Security Policy is present, FALSE otherwise.
bool mIsChannelMaskPresent; ///< TRUE if Channel Mask is present, FALSE otherwise.
bool mIsWakeupChannelPresent; ///< TRUE if Wake-up Channel is present, FALSE otherwise.
} otOperationalDatasetComponents;
/**
@@ -236,7 +235,6 @@ typedef struct otOperationalDataset
uint32_t mDelay; ///< Delay Timer
otPanId mPanId; ///< PAN ID
uint16_t mChannel; ///< Channel
uint16_t mWakeupChannel; ///< Wake-up Channel
otPskc mPskc; ///< PSKc
otSecurityPolicy mSecurityPolicy; ///< Security Policy
otChannelMask mChannelMask; ///< Channel Mask
@@ -303,7 +301,6 @@ typedef enum otMeshcopTlvType
OT_MESHCOP_TLV_SCAN_DURATION = 56, ///< meshcop Scan Duration TLV
OT_MESHCOP_TLV_ENERGY_LIST = 57, ///< meshcop Energy List TLV
OT_MESHCOP_TLV_THREAD_DOMAIN_NAME = 59, ///< meshcop Thread Domain Name TLV
OT_MESHCOP_TLV_WAKEUP_CHANNEL = 74, ///< meshcop Wake-up Channel TLV
OT_MESHCOP_TLV_ADMITTER_STATE = 90, ///< meshcop Admitter State TLV
OT_MESHCOP_TLV_ENROLLER_ID = 91, ///< meshcop Enroller ID TLV
OT_MESHCOP_TLV_ENROLLER_MODE = 92, ///< meshcop Enroller Mode TLV
+1 -1
View File
@@ -52,7 +52,7 @@ extern "C" {
*
* @note This number versions both OpenThread platform and user APIs.
*/
#define OPENTHREAD_API_VERSION (623)
#define OPENTHREAD_API_VERSION (624)
/**
* @addtogroup api-instance
-26
View File
@@ -19,7 +19,6 @@ The Active Operational Dataset includes parameters that are currently in use acr
- Active Timestamp
- Channel
- Wake-up Channel
- Channel Mask
- Extended PAN ID
- Mesh-Local Prefix
@@ -47,7 +46,6 @@ The Pending Operational Dataset is used to communicate changes to the Active Ope
> dataset
Active Timestamp: 1
Channel: 15
Wake-up Channel: 16
Channel Mask: 0x07fff800
Ext PAN ID: 39758ec8144b07fb
Mesh Local Prefix: fdf1:f1ad:d079:7dc0::/64
@@ -107,7 +105,6 @@ After the device successfully attaches to a Thread network, the device will retr
> dataset active
Active Timestamp: 1
Channel: 15
Wake-up Channel: 16
Channel Mask: 0x07fff800
Ext PAN ID: 39758ec8144b07fb
Mesh Local Prefix: fdf1:f1ad:d079:7dc0::/64
@@ -306,7 +303,6 @@ Normally, an active Commissioner will set a new Pending Operational Dataset. For
- [securitypolicy](#securitypolicy)
- [tlvs](#tlvs)
- [updater](#updater)
- [wakeupchannel](#wakeupchannel)
## Command Details
@@ -340,7 +336,6 @@ pskc
securitypolicy
set
tlvs
wakeupchannel
Done
```
@@ -354,7 +349,6 @@ Print Active Operational Dataset in human-readable form.
> dataset active
Active Timestamp: 1
Channel: 15
Wake-up Channel: 16
Channel Mask: 0x07fff800
Ext PAN ID: 39758ec8144b07fb
Mesh Local Prefix: fdf1:f1ad:d079:7dc0::/64
@@ -372,7 +366,6 @@ Print Active Operational Dataset in human-readable form and redact the sensitive
> dataset active -ns
Active Timestamp: 1
Channel: 15
Wake-up Channel: 16
Channel Mask: 0x07fff800
Ext PAN ID: 39758ec8144b07fb
Mesh Local Prefix: fdf1:f1ad:d079:7dc0::/64
@@ -871,22 +864,3 @@ Done
Disabled
Done
```
### wakeupchannel
Usage: `wakeupchannel [channel]`
Get wake-up channel.
```bash
> dataset wakeupchannel
13
Done
```
Set wake-up channel.
```bash
> dataset wakeupchannel 13
Done
```
-30
View File
@@ -134,12 +134,6 @@ const Dataset::ComponentMapper *Dataset::LookupMapper(const char *aName) const
&Dataset::OutputSecurityPolicy,
&Dataset::ParseSecurityPolicy,
},
{
"wakeupchannel",
&Components::mIsWakeupChannelPresent,
&Dataset::OutputWakeupChannel,
&Dataset::ParseWakeupChannel,
},
};
static_assert(BinarySearch::IsSorted(kMappers), "kMappers is not sorted");
@@ -188,24 +182,6 @@ void Dataset::OutputActiveTimestamp(const otOperationalDataset &aDataset)
*/
void Dataset::OutputChannel(const otOperationalDataset &aDataset) { OutputLine("%u", aDataset.mChannel); }
/**
* @cli dataset wakeupchannel (get,set)
* @code
* dataset wakeupchannel
* 13
* Done
* @endcode
* @code
* dataset wakeupchannel 13
* Done
* @endcode
* @cparam dataset wakeupchannel [@ca{channel-num}]
* Use the optional `channel-num` argument to set the wake-up channel.
* @par
* Gets or sets #otOperationalDataset::mWakeupChannel.
*/
void Dataset::OutputWakeupChannel(const otOperationalDataset &aDataset) { OutputLine("%u", aDataset.mWakeupChannel); }
/**
* @cli dataset channelmask (get,set)
* @code
@@ -436,11 +412,6 @@ otError Dataset::ParseChannel(Arg *&aArgs, otOperationalDataset &aDataset)
return aArgs++->ParseAsUint16(aDataset.mChannel);
}
otError Dataset::ParseWakeupChannel(Arg *&aArgs, otOperationalDataset &aDataset)
{
return aArgs++->ParseAsUint16(aDataset.mWakeupChannel);
}
otError Dataset::ParseChannelMask(Arg *&aArgs, otOperationalDataset &aDataset)
{
return aArgs++->ParseAsUint32(aDataset.mChannelMask);
@@ -591,7 +562,6 @@ otError Dataset::Print(otOperationalDatasetTlvs &aDatasetTlvs, bool aNonsensitiv
{"Pending Timestamp", "pendingtimestamp", false},
{"Active Timestamp", "activetimestamp", false},
{"Channel", "channel", false},
{"Wake-up Channel", "wakeupchannel", false},
{"Channel Mask", "channelmask", false},
{"Delay", "delay", false},
{"Ext PAN ID", "extpanid", false},
-2
View File
@@ -92,7 +92,6 @@ private:
void OutputActiveTimestamp(const otOperationalDataset &aDataset);
void OutputChannel(const otOperationalDataset &aDataset);
void OutputWakeupChannel(const otOperationalDataset &aDataset);
void OutputChannelMask(const otOperationalDataset &aDataset);
void OutputDelay(const otOperationalDataset &aDataset);
void OutputExtendedPanId(const otOperationalDataset &aDataset);
@@ -106,7 +105,6 @@ private:
otError ParseActiveTimestamp(Arg *&aArgs, otOperationalDataset &aDataset);
otError ParseChannel(Arg *&aArgs, otOperationalDataset &aDataset);
otError ParseWakeupChannel(Arg *&aArgs, otOperationalDataset &aDataset);
otError ParseChannelMask(Arg *&aArgs, otOperationalDataset &aDataset);
otError ParseDelay(Arg *&aArgs, otOperationalDataset &aDataset);
otError ParseExtendedPanId(Arg *&aArgs, otOperationalDataset &aDataset);
-18
View File
@@ -65,7 +65,6 @@ Error Dataset::Info::GenerateRandom(Instance &aInstance)
mActiveTimestamp.mAuthoritative = false;
mChannel = preferredChannels.ChooseRandomChannel();
mChannelMask = supportedChannels.GetMask();
mWakeupChannel = supportedChannels.ChooseRandomChannel();
mPanId = Mac::GenerateRandomPanId();
AsCoreType(&mSecurityPolicy).SetToDefault();
@@ -83,7 +82,6 @@ Error Dataset::Info::GenerateRandom(Instance &aInstance)
mComponents.mIsMeshLocalPrefixPresent = true;
mComponents.mIsPanIdPresent = true;
mComponents.mIsChannelPresent = true;
mComponents.mIsWakeupChannelPresent = true;
mComponents.mIsPskcPresent = true;
mComponents.mIsSecurityPolicyPresent = true;
mComponents.mIsChannelMaskPresent = true;
@@ -159,7 +157,6 @@ bool Dataset::IsTlvValid(const Tlv &aTlv)
minLength = sizeof(MeshLocalPrefixTlv::ValueType);
break;
case Tlv::kChannel:
case Tlv::kWakeupChannel:
minLength = sizeof(ChannelTlvValue);
break;
default:
@@ -190,9 +187,6 @@ bool Dataset::IsTlvValid(const Tlv &aTlv)
case Tlv::kChannel:
isValid = aTlv.ReadValueAs<ChannelTlv>().IsValid();
break;
case Tlv::kWakeupChannel:
isValid = aTlv.ReadValueAs<WakeupChannelTlv>().IsValid();
break;
case Tlv::kNetworkName:
isValid = As<NetworkNameTlv>(aTlv).IsValid();
break;
@@ -272,10 +266,6 @@ void Dataset::ConvertTo(Info &aDatasetInfo) const
aDatasetInfo.Set<kChannel>(cur->ReadValueAs<ChannelTlv>().GetChannel());
break;
case Tlv::kWakeupChannel:
aDatasetInfo.Set<kWakeupChannel>(cur->ReadValueAs<WakeupChannelTlv>().GetChannel());
break;
case Tlv::kChannelMask:
{
uint32_t mask;
@@ -474,14 +464,6 @@ Error Dataset::WriteTlvsFrom(const Dataset::Info &aDatasetInfo)
SuccessOrExit(error = Write<ChannelTlv>(channelValue));
}
if (aDatasetInfo.IsPresent<kWakeupChannel>())
{
ChannelTlvValue channelValue;
channelValue.SetChannelAndPage(aDatasetInfo.Get<kWakeupChannel>());
SuccessOrExit(error = Write<WakeupChannelTlv>(channelValue));
}
if (aDatasetInfo.IsPresent<kChannelMask>())
{
ChannelMaskTlv::Value value;
-5
View File
@@ -89,7 +89,6 @@ public:
kDelay, ///< Delay
kPanId, ///< PAN Identifier
kChannel, ///< Channel
kWakeupChannel, ///< Wakeup Channel
kPskc, ///< PSKc
kSecurityPolicy, ///< Security Policy
kChannelMask, ///< Channel Mask
@@ -733,7 +732,6 @@ DefineIsPresentAndMarkAsPresent(MeshLocalPrefix)
DefineIsPresentAndMarkAsPresent(Delay)
DefineIsPresentAndMarkAsPresent(PanId)
DefineIsPresentAndMarkAsPresent(Channel)
DefineIsPresentAndMarkAsPresent(WakeupChannel)
DefineIsPresentAndMarkAsPresent(Pskc)
DefineIsPresentAndMarkAsPresent(SecurityPolicy)
DefineIsPresentAndMarkAsPresent(ChannelMask)
@@ -752,7 +750,6 @@ template <> struct Dataset::TypeFor<Dataset::kMeshLocalPrefix> { using Type = I
template <> struct Dataset::TypeFor<Dataset::kDelay> { using Type = uint32_t; };
template <> struct Dataset::TypeFor<Dataset::kPanId> { using Type = Mac::PanId; };
template <> struct Dataset::TypeFor<Dataset::kChannel> { using Type = uint16_t; };
template <> struct Dataset::TypeFor<Dataset::kWakeupChannel> { using Type = uint16_t; };
template <> struct Dataset::TypeFor<Dataset::kPskc> { using Type = Pskc; };
template <> struct Dataset::TypeFor<Dataset::kSecurityPolicy> { using Type = SecurityPolicy; };
template <> struct Dataset::TypeFor<Dataset::kChannelMask> { using Type = uint32_t; };
@@ -788,8 +785,6 @@ template <> inline const Mac::PanId &Dataset::Info::Get<Dataset::kPanId>(void) c
template <> inline const uint16_t &Dataset::Info::Get<Dataset::kChannel>(void) const { return mChannel; }
template <> inline const uint16_t &Dataset::Info::Get<Dataset::kWakeupChannel>(void) const { return mWakeupChannel; }
template <> inline const Pskc &Dataset::Info::Get<Dataset::kPskc>(void) const { return AsCoreType(&mPskc); }
template <> inline const SecurityPolicy &Dataset::Info::Get<Dataset::kSecurityPolicy>(void) const
-5
View File
@@ -657,11 +657,6 @@ Error DatasetManager::SendGetRequest(const Dataset::Components &aDatasetComponen
tlvList.Add(Tlv::kChannel);
}
if (aDatasetComponents.IsPresent<Dataset::kWakeupChannel>())
{
tlvList.Add(Tlv::kWakeupChannel);
}
if (aDatasetComponents.IsPresent<Dataset::kPskc>())
{
tlvList.Add(Tlv::kPskc);
-8
View File
@@ -239,14 +239,6 @@ Error ActiveDatasetManager::GenerateLocal(void)
IgnoreError(dataset.Write<ChannelTlv>(channelValue));
}
if (!dataset.Contains<WakeupChannelTlv>())
{
ChannelTlvValue channelValue;
channelValue.SetChannelAndPage(Get<Mac::Mac>().GetWakeupChannel());
IgnoreError(dataset.Write<WakeupChannelTlv>(channelValue));
}
if (!dataset.Contains<ChannelMaskTlv>())
{
ChannelMaskTlv::Value value;
-6
View File
@@ -112,7 +112,6 @@ public:
kScanDuration = OT_MESHCOP_TLV_SCAN_DURATION, ///< Scan Duration TLV
kEnergyList = OT_MESHCOP_TLV_ENERGY_LIST, ///< Energy List TLV
kThreadDomainName = OT_MESHCOP_TLV_THREAD_DOMAIN_NAME, ///< Thread Domain Name TLV
kWakeupChannel = OT_MESHCOP_TLV_WAKEUP_CHANNEL, ///< Wakeup Channel TLV
kAdmitterState = OT_MESHCOP_TLV_ADMITTER_STATE, ///< Admitter State TLV
kEnrollerId = OT_MESHCOP_TLV_ENROLLER_ID, ///< Enroller ID TLV
kEnrollerMode = OT_MESHCOP_TLV_ENROLLER_MODE, ///< Enroller Mode TLV
@@ -246,11 +245,6 @@ typedef Mle::ChannelTlvValue ChannelTlvValue;
*/
typedef SimpleTlvInfo<Tlv::kChannel, ChannelTlvValue> ChannelTlv;
/**
* Defines Wake-up Channel TLV constants and types.
*/
typedef SimpleTlvInfo<Tlv::kWakeupChannel, ChannelTlvValue> WakeupChannelTlv;
/**
* Defines PAN ID TLV constants and types.
*/
-1
View File
@@ -98,7 +98,6 @@ public:
kPendingDataset = 25, ///< Pending Operational Dataset TLV
kDiscovery = 26, ///< Thread Discovery TLV
kSupervisionInterval = 27, ///< Supervision Interval TLV
kWakeupChannel = 74, ///< Wakeup Channel TLV
kCslChannel = 80, ///< CSL Channel TLV
kCslTimeout = 85, ///< CSL Timeout TLV
kCslClockAccuracy = 86, ///< CSL Clock Accuracy TLV
+3 -11
View File
@@ -2083,7 +2083,6 @@ class OTCI(object):
#
# Active Timestamp: 1
# Channel: 22
# Wake-up Channel: 11
# Channel Mask: 0x07fff800
# Ext PAN ID: 5c93ae980ff22d35
# Mesh Local Prefix: fdc7:55fe:6363:bd01::/64
@@ -2103,8 +2102,6 @@ class OTCI(object):
dataset['active_timestamp'] = int(val)
elif key == 'Channel':
dataset['channel'] = int(val)
elif key == 'Wake-up Channel':
dataset['wakeupchannel'] = int(val)
elif key == 'Channel Mask':
dataset['channel_mask'] = int(val, 16)
elif key == 'Ext PAN ID':
@@ -2153,7 +2150,6 @@ class OTCI(object):
def dataset_set_buffer(self,
active_timestamp: Optional[int] = None,
channel: Optional[int] = None,
wakeupchannel: Optional[int] = None,
channel_mask: Optional[int] = None,
extpanid: Optional[str] = None,
mesh_local_prefix: Optional[str] = None,
@@ -2169,9 +2165,6 @@ class OTCI(object):
if channel is not None:
self.execute_command(f'dataset channel {channel}')
if wakeupchannel is not None:
self.execute_command(f'dataset wakeupchannel {wakeupchannel}')
if channel_mask is not None:
self.execute_command(f'dataset channelmask {channel_mask:#08x}')
@@ -3289,13 +3282,12 @@ class OTCI(object):
panid: Optional[int] = None,
pskc: Optional[str] = None,
security_policy: Optional[tuple[int, str]] = None,
pending_timestamp: Optional[int] = None,
wakeup_channel: Optional[int] = None) -> bytes:
pending_timestamp: Optional[int] = None) -> bytes:
"""Creates a new Operational Dataset with given parameters."""
self.dataset_clear_buffer()
self.dataset_init_buffer()
self.dataset_set_buffer(active_timestamp, channel, wakeup_channel, channel_mask, extpanid, mesh_local_prefix,
network_key, network_name, panid, pskc, security_policy, pending_timestamp)
self.dataset_set_buffer(active_timestamp, channel, channel_mask, extpanid, mesh_local_prefix, network_key,
network_name, panid, pskc, security_policy, pending_timestamp)
return self.get_dataset_tlvs_bytes()
def join(self, dataset: bytes) -> None:
@@ -492,30 +492,6 @@ class ChannelMaskEntry(DatasetEntry):
return TLV.from_bytes(tlv)
class WakeupChannel(DatasetEntry):
def __init__(self):
super().__init__(MeshcopTlvType.WAKEUP_CHANNEL)
self.length = 3 # spec defined
self.channel_page = 0
self.channel = 0
def set(self, args: List[str]):
if len(args) == 0:
raise ValueError('No argument for WakeupChannel')
channel = int(args[0])
self.channel = channel
def set_from_tlv(self, tlv: TLV):
self.channel = int.from_bytes(tlv.value[1:3], byteorder='big')
self.channel_page = tlv.value[0]
def to_tlv(self):
tlv = struct.pack('>BBB', self.type.value, self.length, self.channel_page)
tlv += struct.pack('>H', self.channel)
return TLV.from_bytes(tlv)
ENTRY_CLASSES = {
MeshcopTlvType.ACTIVETIMESTAMP: ActiveTimestamp,
MeshcopTlvType.PENDINGTIMESTAMP: PendingTimestamp,
@@ -529,7 +505,6 @@ ENTRY_CLASSES = {
MeshcopTlvType.PSKC: Pskc,
MeshcopTlvType.SECURITYPOLICY: SecurityPolicy,
MeshcopTlvType.CHANNELMASK: ChannelMask,
MeshcopTlvType.WAKEUP_CHANNEL: WakeupChannel
}
-1
View File
@@ -68,7 +68,6 @@ class MeshcopTlvType(Enum):
SCAN_DURATION = 56
ENERGY_LIST = 57
THREAD_DOMAIN_NAME = 59
WAKEUP_CHANNEL = 74
DISCOVERYREQUEST = 128
DISCOVERYRESPONSE = 129
JOINERADVERTISEMENT = 241