diff --git a/include/openthread/instance.h b/include/openthread/instance.h index ed9c69ba3..30d0c427b 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (50) +#define OPENTHREAD_API_VERSION (51) /** * @addtogroup api-instance diff --git a/include/openthread/thread_ftd.h b/include/openthread/thread_ftd.h index 134936fa5..11c15ce23 100644 --- a/include/openthread/thread_ftd.h +++ b/include/openthread/thread_ftd.h @@ -219,23 +219,23 @@ uint8_t otThreadGetLocalLeaderWeight(otInstance *aInstance); void otThreadSetLocalLeaderWeight(otInstance *aInstance, uint8_t aWeight); /** - * Get the Thread Leader Partition Id used when operating in the Leader role. + * Get the preferred Thread Leader Partition Id used when operating in the Leader role. * * @param[in] aInstance A pointer to an OpenThread instance. * * @returns The Thread Leader Partition Id value. * */ -uint32_t otThreadGetLocalLeaderPartitionId(otInstance *aInstance); +uint32_t otThreadGetPreferredLeaderPartitionId(otInstance *aInstance); /** - * Set the Thread Leader Partition Id used when operating in the Leader role. + * Set the preferred Thread Leader Partition Id used when operating in the Leader role. * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aPartitionId The Thread Leader Partition Id value. * */ -void otThreadSetLocalLeaderPartitionId(otInstance *aInstance, uint32_t aPartitionId); +void otThreadSetPreferredLeaderPartitionId(otInstance *aInstance, uint32_t aPartitionId); /** * Get the Joiner UDP Port. diff --git a/src/cli/README.md b/src/cli/README.md index ef807ecbb..5edca1ab9 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -57,7 +57,6 @@ Done - [joinerport](#joinerport-port) - [keysequence](#keysequence-counter) - [leaderdata](#leaderdata) -- [leaderpartitionid](#leaderpartitionid) - [leaderweight](#leaderweight) - [linkmetrics](#linkmetrics-mgmt-ipaddr-forward-seriesid-ldraxpqmr) - [linkquality](#linkquality-extaddr) @@ -77,6 +76,7 @@ Done - [panid](#panid) - [parent](#parent) - [parentpriority](#parentpriority) +- [partitionid](#partitionid) - [ping](#ping-ipaddr-sizecount-intervalhoplimit) - [pollperiod](#pollperiod-pollperiod) - [preferrouterid](#preferrouterid-routerid) @@ -1093,25 +1093,6 @@ Set Thread Key Switch Guard Time (in hours) 0 means Thread Key Switch imediately Done ``` -### leaderpartitionid - -Get the Thread Leader Partition ID. - -```bash -> leaderpartitionid -4294967295 -Done -``` - -### leaderpartitionid \ - -Set the Thread Leader Partition ID. - -```bash -> leaderpartitionid 0xffffffff -Done -``` - ### leaderdata Show the Thread Leader Data. @@ -1518,6 +1499,39 @@ Set the assigned parent priority value: 1, 0, -1 or -2. Done ``` +### partitionid + +Get the Thread Network Partition ID. + +```bash +> partitionid +4294967295 +Done +``` + +### partitionid preferred + +Get the preferred Thread Leader Partition ID. + +`OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is required. + +```bash +> partitionid preferred +4294967295 +Done +``` + +### partitionid preferred \ + +Set the preferred Thread Leader Partition ID. + +`OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is required. + +```bash +> partitionid preferred 0xffffffff +Done +``` + ### ping \ [size][count] [interval][hoplimit] Send an ICMPv6 Echo Request. diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 2926a7fdb..553546dd1 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -1881,23 +1881,37 @@ exit: } #if OPENTHREAD_FTD -otError Interpreter::ProcessLeaderPartitionId(uint8_t aArgsLength, char *aArgs[]) +otError Interpreter::ProcessPartitionId(uint8_t aArgsLength, char *aArgs[]) { - otError error = OT_ERROR_NONE; + OT_UNUSED_VARIABLE(aArgs); + + otError error = OT_ERROR_INVALID_COMMAND; if (aArgsLength == 0) { - OutputLine("%u", otThreadGetLocalLeaderPartitionId(mInstance)); + OutputLine("%u", otThreadGetPartitionId(mInstance)); + error = OT_ERROR_NONE; } - else +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + else if (strcmp(aArgs[0], "preferred") == 0) { - uint32_t partitionId; + if (aArgsLength == 1) + { + OutputLine("%u", otThreadGetPreferredLeaderPartitionId(mInstance)); + error = OT_ERROR_NONE; + } + else if (aArgsLength == 2) + { + uint32_t partitionId; - SuccessOrExit(error = ParseAsUint32(aArgs[0], partitionId)); - otThreadSetLocalLeaderPartitionId(mInstance, partitionId); + SuccessOrExit(error = ParseAsUint32(aArgs[1], partitionId)); + otThreadSetPreferredLeaderPartitionId(mInstance, partitionId); + } } exit: +#endif + return error; } diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index a2c931215..6d3576dbd 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -381,7 +381,7 @@ private: otError ProcessKeySequence(uint8_t aArgsLength, char *aArgs[]); otError ProcessLeaderData(uint8_t aArgsLength, char *aArgs[]); #if OPENTHREAD_FTD - otError ProcessLeaderPartitionId(uint8_t aArgsLength, char *aArgs[]); + otError ProcessPartitionId(uint8_t aArgsLength, char *aArgs[]); otError ProcessLeaderWeight(uint8_t aArgsLength, char *aArgs[]); #endif otError ProcessMasterKey(uint8_t aArgsLength, char *aArgs[]); @@ -661,7 +661,6 @@ private: {"keysequence", &Interpreter::ProcessKeySequence}, {"leaderdata", &Interpreter::ProcessLeaderData}, #if OPENTHREAD_FTD - {"leaderpartitionid", &Interpreter::ProcessLeaderPartitionId}, {"leaderweight", &Interpreter::ProcessLeaderWeight}, #endif #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE @@ -699,6 +698,7 @@ private: {"parent", &Interpreter::ProcessParent}, #if OPENTHREAD_FTD {"parentpriority", &Interpreter::ProcessParentPriority}, + {"partitionid", &Interpreter::ProcessPartitionId}, #endif {"ping", &Interpreter::ProcessPing}, {"pollperiod", &Interpreter::ProcessPollPeriod}, diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp index 712773872..66e8151b4 100644 --- a/src/core/api/thread_ftd_api.cpp +++ b/src/core/api/thread_ftd_api.cpp @@ -110,19 +110,21 @@ void otThreadSetLocalLeaderWeight(otInstance *aInstance, uint8_t aWeight) instance.Get().SetLeaderWeight(aWeight); } -uint32_t otThreadGetLocalLeaderPartitionId(otInstance *aInstance) +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE +uint32_t otThreadGetPreferredLeaderPartitionId(otInstance *aInstance) { Instance &instance = *static_cast(aInstance); - return instance.Get().GetLeaderPartitionId(); + return instance.Get().GetPreferredLeaderPartitionId(); } -void otThreadSetLocalLeaderPartitionId(otInstance *aInstance, uint32_t aPartitionId) +void otThreadSetPreferredLeaderPartitionId(otInstance *aInstance, uint32_t aPartitionId) { Instance &instance = *static_cast(aInstance); - return instance.Get().SetLeaderPartitionId(aPartitionId); + instance.Get().SetPreferredLeaderPartitionId(aPartitionId); } +#endif uint16_t otThreadGetJoinerUdpPort(otInstance *aInstance) { diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 345277594..71073a3c3 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -67,7 +67,9 @@ MleRouter::MleRouter(Instance &aInstance) , mRouterUpgradeThreshold(kRouterUpgradeThreshold) , mRouterDowngradeThreshold(kRouterDowngradeThreshold) , mLeaderWeight(kLeaderWeight) - , mFixedLeaderPartitionId(0) +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + , mPreferredLeaderPartitionId(0) +#endif , mRouterEligible(true) , mAddressSolicitPending(false) , mAddressSolicitRejected(false) @@ -191,7 +193,11 @@ otError MleRouter::BecomeLeader(void) mRouterTable.Clear(); - partitionId = mFixedLeaderPartitionId ? mFixedLeaderPartitionId : Random::NonCrypto::GetUint32(); +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + partitionId = mPreferredLeaderPartitionId ? mPreferredLeaderPartitionId : Random::NonCrypto::GetUint32(); +#else + partitionId = Random::NonCrypto::GetUint32(); +#endif leaderId = IsRouterIdValid(mPreviousRouterId) ? mPreviousRouterId : Random::NonCrypto::GetUint8InRange(0, kMaxRouterId + 1); diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index 33c712076..4ce2a1069 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -157,21 +157,24 @@ public: */ void SetLeaderWeight(uint8_t aWeight) { mLeaderWeight = aWeight; } - /** - * This method returns the fixed Partition Id of Thread network partition for certification testing. - * - * @returns The Partition Id for this Thread network partition. - * - */ - uint32_t GetLeaderPartitionId(void) const { return mFixedLeaderPartitionId; } +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE /** - * This method sets the fixed Partition Id for Thread network partition for certification testing. + * This method returns the preferred Partition Id when operating in the Leader role for certification testing. * - * @param[in] aPartitionId The Leader Partition Id. + * @returns The preferred Partition Id value. * */ - void SetLeaderPartitionId(uint32_t aPartitionId) { mFixedLeaderPartitionId = aPartitionId; } + uint32_t GetPreferredLeaderPartitionId(void) const { return mPreferredLeaderPartitionId; } + + /** + * This method sets the preferred Partition Id when operating in the Leader role for certification testing. + * + * @param[in] aPartitionId The preferred Leader Partition Id. + * + */ + void SetPreferredLeaderPartitionId(uint32_t aPartitionId) { mPreferredLeaderPartitionId = aPartitionId; } +#endif /** * This method sets the preferred Router Id. Upon becoming a router/leader the node @@ -671,10 +674,12 @@ private: uint8_t mRouterUpgradeThreshold; uint8_t mRouterDowngradeThreshold; uint8_t mLeaderWeight; - uint32_t mFixedLeaderPartitionId; ///< only for certification testing - bool mRouterEligible : 1; - bool mAddressSolicitPending : 1; - bool mAddressSolicitRejected : 1; +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + uint32_t mPreferredLeaderPartitionId; ///< only for certification testing +#endif + bool mRouterEligible : 1; + bool mAddressSolicitPending : 1; + bool mAddressSolicitRejected : 1; uint8_t mRouterId; uint8_t mPreviousRouterId; diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index 2d13ea430..629b942c6 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -388,7 +388,9 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey) OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NET_MASTER_KEY), OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER), #if OPENTHREAD_FTD +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NET_PARTITION_ID), +#endif #endif OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING), OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME), diff --git a/src/ncp/ncp_base_ftd.cpp b/src/ncp/ncp_base_ftd.cpp index 1533d419e..72f6718e2 100644 --- a/src/ncp/ncp_base_ftd.cpp +++ b/src/ncp/ncp_base_ftd.cpp @@ -348,6 +348,7 @@ exit: return error; } +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE template <> otError NcpBase::HandlePropertySet(void) { uint32_t partitionId = 0; @@ -355,11 +356,12 @@ template <> otError NcpBase::HandlePropertySet(voi SuccessOrExit(error = mDecoder.ReadUint32(partitionId)); - otThreadSetLocalLeaderPartitionId(mInstance, partitionId); + otThreadSetPreferredLeaderPartitionId(mInstance, partitionId); exit: return error; } +#endif template <> otError NcpBase::HandlePropertyGet(void) { diff --git a/tests/scripts/expect/cli-partitionid.exp b/tests/scripts/expect/cli-partitionid.exp new file mode 100644 index 000000000..e2e0b6039 --- /dev/null +++ b/tests/scripts/expect/cli-partitionid.exp @@ -0,0 +1,45 @@ +#!/usr/bin/expect -f +# +# Copyright (c) 2020, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +source "tests/scripts/expect/_common.exp" + +spawn_node 1 + +send "partitionid preferred 12345678\n" +expect "Done" +send "partitionid preferred\n" +expect "12345678" +expect "Done" +send "partitionid invalid\n" +expect "Error 35: InvalidCommand" +send "partitionid\n" +expect "0" +expect "Done" + +dispose_all diff --git a/tests/scripts/thread-cert/Cert_5_5_03_SplitMergeChildren.py b/tests/scripts/thread-cert/Cert_5_5_03_SplitMergeChildren.py index 1d5cdd6b8..dd6ef567d 100755 --- a/tests/scripts/thread-cert/Cert_5_5_03_SplitMergeChildren.py +++ b/tests/scripts/thread-cert/Cert_5_5_03_SplitMergeChildren.py @@ -114,7 +114,7 @@ class Cert_5_5_3_SplitMergeChildren(thread_cert.TestCase): self.nodes[LEADER].reset() self._setUpLeader() - self.nodes[ROUTER2].set_partition_id(0xffffffff) + self.nodes[ROUTER2].set_preferred_partition_id(0xffffffff) self.simulator.go(140) diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py index eb1c4657a..6f88a6afb 100755 --- a/tests/scripts/thread-cert/node.py +++ b/tests/scripts/thread-cert/node.py @@ -939,12 +939,12 @@ class NodeImpl: self.send_command(cmd) self._expect('Done') - def get_partition_id(self): - self.send_command('leaderpartitionid') + def get_preferred_partition_id(self): + self.send_command('partitionid preferred') return self._expect_result(r'\d+') - def set_partition_id(self, partition_id): - cmd = 'leaderpartitionid %d' % partition_id + def set_preferred_partition_id(self, partition_id): + cmd = 'partitionid preferred %d' % partition_id self.send_command(cmd) self._expect('Done') diff --git a/tests/scripts/thread-cert/thread_cert.py b/tests/scripts/thread-cert/thread_cert.py index 2d24e5475..b20801602 100644 --- a/tests/scripts/thread-cert/thread_cert.py +++ b/tests/scripts/thread-cert/thread_cert.py @@ -161,7 +161,7 @@ class TestCase(NcpSupportMixin, unittest.TestCase): self.nodes[i].set_mode(params['mode']) if 'partition_id' in params: - self.nodes[i].set_partition_id(params['partition_id']) + self.nodes[i].set_preferred_partition_id(params['partition_id']) if 'channel' in params: self.nodes[i].set_channel(params['channel']) if 'masterkey' in params: diff --git a/tests/toranj/openthread-core-toranj-config.h b/tests/toranj/openthread-core-toranj-config.h index dc4a5c106..55e481685 100644 --- a/tests/toranj/openthread-core-toranj-config.h +++ b/tests/toranj/openthread-core-toranj-config.h @@ -39,6 +39,14 @@ #define OPENTHREAD_RADIO 0 #endif +/** + * @def OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + * + * Define to 1 to enable Thread Test Harness reference device support. + * + */ +#define OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 1 + /** * @def OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE * diff --git a/tools/harness-thci/OpenThread.py b/tools/harness-thci/OpenThread.py index 25ffa2836..c5c4ed5f9 100644 --- a/tools/harness-thci/OpenThread.py +++ b/tools/harness-thci/OpenThread.py @@ -1930,7 +1930,7 @@ class OpenThreadTHCI(object): print('%s call setPartationId' % self) print(partationId) - cmd = 'leaderpartitionid %s' % (str(hex(partationId)).rstrip('L')) + cmd = 'partitionid preferred %s' % (str(hex(partationId)).rstrip('L')) print(cmd) return self.__executeCommand(cmd)[-1] == 'Done'