[ncp] add support for Joiner Discerner and getting list of joiners (#5137)

This commit adds/updates spinel properties to add Joiner Discerner
support on joiner and commissioner side. It also adds support for
getting the list of joiners on commissioner by implementing property
get handler for spinel property `MESHCOP_COMMISSIONER_JOINERS`.
This commit is contained in:
Abtin Keshavarzian
2020-06-26 16:02:09 -07:00
committed by Jonathan Hui
parent c7dc2be7d2
commit a7415b53a4
5 changed files with 177 additions and 20 deletions
+4
View File
@@ -1891,6 +1891,10 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
ret = "MESHCOP_COMMISSIONER_SESSION_ID";
break;
case SPINEL_PROP_MESHCOP_JOINER_DISCERNER:
ret = "MESHCOP_JOINER_DISCERNER";
break;
case SPINEL_PROP_MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN:
ret = "MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN";
break;
+38 -5
View File
@@ -3112,15 +3112,22 @@ enum
SPINEL_PROP_MESHCOP_COMMISSIONER_STATE = SPINEL_PROP_MESHCOP__BEGIN + 2,
// Thread Commissioner Joiners
/** Format `A(t(E)UL)` - insert or remove only
/** Format `A(t(t(E|CX)UL))` - get, insert or remove.
*
* Required capability: SPINEL_CAP_THREAD_COMMISSIONER
*
* Data per item is:
* Data per array entry is:
*
* `t(E)` | `t()`: Joiner EUI64. Empty struct indicates any Joiner
* `L` : Timeout (in seconds) after which the Joiner is automatically removed
* `U` : PSKd
* `t()` | `t(E)` | `t(CX)` : Joiner info struct (formatting varies).
*
* - `t()` or empty struct indicates any joiner.
* - `t(E)` specifies the Joiner EUI-64.
* - `t(CX) specifies Joiner Discerner, `C` is Discerner length (in bits), and `X` is Discerner value.
*
* The struct is followed by:
*
* `L` : Timeout after which to remove Joiner (when written should be in seconds, when read is in milliseconds)
* `U` : PSKd
*
* For CMD_PROP_VALUE_REMOVE the timeout and PSKd are optional.
*
@@ -3143,6 +3150,32 @@ enum
*/
SPINEL_PROP_MESHCOP_COMMISSIONER_SESSION_ID = SPINEL_PROP_MESHCOP__BEGIN + 5,
/// Thread Joiner Discerner
/** Format `CX` - Read-write
*
* Required capability: SPINEL_CAP_THREAD_JOINER
*
* This property represents a Joiner Discerner.
*
* The Joiner Discerner is used to calculate the Joiner ID used during commissioning/joining process.
*
* By default (when a discerner is not provided or cleared), Joiner ID is derived as first 64 bits of the result
* of computing SHA-256 over factory-assigned IEEE EUI-64. Note that this is the main behavior expected by Thread
* specification.
*
* Format:
*
* 'C' : The Joiner Discerner bit length (number of bits).
* `X` : The Joiner Discerner value (64-bit unsigned) - Only present/applicable when length is non-zero.
*
* When writing to this property, the length can be set to zero to clear any previously set Joiner Discerner value.
*
* When reading this property if there is no currently set Joiner Discerner, zero is returned as the length (with
* no value field).
*
*/
SPINEL_PROP_MESHCOP_JOINER_DISCERNER = SPINEL_PROP_MESHCOP__BEGIN + 6,
SPINEL_PROP_MESHCOP__END = 0x90,
SPINEL_PROP_MESHCOP_EXT__BEGIN = 0x1800,
+7
View File
@@ -135,10 +135,14 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
#if OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MESHCOP_COMMISSIONER_STATE),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MESHCOP_COMMISSIONER_PROVISIONING_URL),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MESHCOP_COMMISSIONER_SESSION_ID),
#endif
#endif // OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_JOINER_ENABLE
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MESHCOP_JOINER_DISCERNER),
#endif
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SERVER_SERVICES),
@@ -404,6 +408,9 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MESHCOP_COMMISSIONER_PROVISIONING_URL),
#endif
#endif // OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_JOINER_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MESHCOP_JOINER_DISCERNER),
#endif
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE),
#endif
+87 -14
View File
@@ -538,23 +538,72 @@ exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS>(void)
{
otError error = OT_ERROR_NONE;
uint16_t iter = 0;
otJoinerInfo joinerInfo;
while (otCommissionerGetNextJoinerInfo(mInstance, &iter, &joinerInfo) == OT_ERROR_NONE)
{
SuccessOrExit(error = mEncoder.OpenStruct());
SuccessOrExit(error = mEncoder.OpenStruct()); // Joiner Id (any, EUI64 or a Joiner Discerner) struct
switch (joinerInfo.mType)
{
case OT_JOINER_INFO_TYPE_ANY:
break;
case OT_JOINER_INFO_TYPE_EUI64:
SuccessOrExit(error = mEncoder.WriteEui64(joinerInfo.mSharedId.mEui64));
break;
case OT_JOINER_INFO_TYPE_DISCERNER:
SuccessOrExit(error = mEncoder.WriteUint8(joinerInfo.mSharedId.mDiscerner.mLength));
SuccessOrExit(error = mEncoder.WriteUint64(joinerInfo.mSharedId.mDiscerner.mValue));
break;
}
SuccessOrExit(error = mEncoder.CloseStruct());
SuccessOrExit(error = mEncoder.WriteUint32(joinerInfo.mExpirationTime));
SuccessOrExit(error = mEncoder.WriteUtf8(joinerInfo.mPskd.m8));
SuccessOrExit(error = mEncoder.CloseStruct());
}
exit:
return error;
}
template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS>(void)
{
otError error = OT_ERROR_NONE;
otJoinerDiscerner discerner;
bool withDiscerner = false;
const otExtAddress *eui64;
uint32_t timeout;
const char * psk;
SuccessOrExit(error = mDecoder.OpenStruct());
if (!mDecoder.IsAllReadInStruct())
switch (mDecoder.GetRemainingLengthInStruct())
{
SuccessOrExit(error = mDecoder.ReadEui64(eui64));
}
else
{
// Empty struct indicates any Joiner (no EUI64 is given so nullptr is used.).
case 0:
// Empty struct indicates any joiner
eui64 = nullptr;
break;
case sizeof(spinel_eui64_t):
SuccessOrExit(error = mDecoder.ReadEui64(eui64));
break;
default:
SuccessOrExit(error = mDecoder.ReadUint8(discerner.mLength));
SuccessOrExit(error = mDecoder.ReadUint64(discerner.mValue));
withDiscerner = true;
break;
}
SuccessOrExit(error = mDecoder.CloseStruct());
@@ -562,7 +611,14 @@ template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_MESHCOP_COMMISSION
SuccessOrExit(error = mDecoder.ReadUint32(timeout));
SuccessOrExit(error = mDecoder.ReadUtf8(psk));
error = otCommissionerAddJoiner(mInstance, eui64, psk, timeout);
if (withDiscerner)
{
error = otCommissionerAddJoinerWithDiscerner(mInstance, &discerner, psk, timeout);
}
else
{
error = otCommissionerAddJoiner(mInstance, eui64, psk, timeout);
}
exit:
return error;
@@ -571,23 +627,40 @@ exit:
template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS>(void)
{
otError error = OT_ERROR_NONE;
otJoinerDiscerner discerner;
bool withDiscerner = false;
const otExtAddress *eui64;
SuccessOrExit(error = mDecoder.OpenStruct());
if (!mDecoder.IsAllReadInStruct())
switch (mDecoder.GetRemainingLengthInStruct())
{
SuccessOrExit(error = mDecoder.ReadEui64(eui64));
}
else
{
// Empty struct indicates any Joiner (no EUI64 is given so nullptr is used.).
case 0:
// Empty struct indicates any joiner
eui64 = nullptr;
break;
case sizeof(spinel_eui64_t):
SuccessOrExit(error = mDecoder.ReadEui64(eui64));
break;
default:
SuccessOrExit(error = mDecoder.ReadUint8(discerner.mLength));
SuccessOrExit(error = mDecoder.ReadUint64(discerner.mValue));
withDiscerner = true;
break;
}
SuccessOrExit(error = mDecoder.CloseStruct());
error = otCommissionerRemoveJoiner(mInstance, eui64);
if (withDiscerner)
{
error = otCommissionerRemoveJoinerWithDiscerner(mInstance, &discerner);
}
else
{
error = otCommissionerRemoveJoiner(mInstance, eui64);
}
exit:
return error;
+41 -1
View File
@@ -1532,7 +1532,47 @@ exit:
return error;
}
#endif
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_JOINER_DISCERNER>(void)
{
otError error;
const otJoinerDiscerner *discerner = otJoinerGetDiscerner(mInstance);
if (discerner == nullptr)
{
SuccessOrExit(error = mEncoder.WriteUint8(0));
}
else
{
SuccessOrExit(error = mEncoder.WriteUint8(discerner->mLength));
SuccessOrExit(error = mEncoder.WriteUint64(discerner->mValue));
}
exit:
return error;
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_JOINER_DISCERNER>(void)
{
otError error = OT_ERROR_NONE;
otJoinerDiscerner discerner;
SuccessOrExit(error = mDecoder.ReadUint8(discerner.mLength));
if (discerner.mLength == 0)
{
// Clearing any previously set Joiner Discerner
error = otJoinerSetDiscerner(mInstance, nullptr);
ExitNow();
}
SuccessOrExit(error = mDecoder.ReadUint64(discerner.mValue));
error = otJoinerSetDiscerner(mInstance, &discerner);
exit:
return error;
}
#endif // OPENTHREAD_CONFIG_JOINER_ENABLE
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_IPV6_ML_PREFIX>(void)
{