[spinel] add multicast listener registration (#6231)

This commit adds Multicast Listeners Register Request and Response
spinel properties:
- SPINEL_PROP_THREAD_MLR_REQUEST
- SPINEL_PROP_THREAD_MLR_RESPONSE
This commit is contained in:
Piotr Koziar
2021-03-18 12:57:10 -07:00
committed by GitHub
parent 0f7401b866
commit 3d10c90da4
6 changed files with 156 additions and 0 deletions
+3
View File
@@ -1350,6 +1350,8 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
SPINEL_PROP_CSTR(THREAD_CSL_TIMEOUT),
SPINEL_PROP_CSTR(THREAD_CSL_CHANNEL),
SPINEL_PROP_CSTR(THREAD_DOMAIN_NAME),
SPINEL_PROP_CSTR(THREAD_MLR_REQUEST),
SPINEL_PROP_CSTR(THREAD_MLR_RESPONSE),
SPINEL_PROP_CSTR(THREAD_BACKBONE_ROUTER_PRIMARY),
SPINEL_PROP_CSTR(THREAD_BACKBONE_ROUTER_LOCAL_STATE),
SPINEL_PROP_CSTR(THREAD_BACKBONE_ROUTER_LOCAL_CONFIG),
@@ -1539,6 +1541,7 @@ const char *spinel_status_to_cstr(spinel_status_t status)
SPINEL_STATUS_CSTR(ALREADY),
SPINEL_STATUS_CSTR(ITEM_NOT_FOUND),
SPINEL_STATUS_CSTR(INVALID_COMMAND_FOR_PROP),
SPINEL_STATUS_CSTR(RESPONSE_TIMEOUT),
SPINEL_STATUS_CSTR(JOIN_FAILURE),
SPINEL_STATUS_CSTR(JOIN_SECURITY),
SPINEL_STATUS_CSTR(JOIN_NO_PEERS),
+48
View File
@@ -466,6 +466,7 @@ enum
SPINEL_STATUS_ALREADY = 19, ///< The operation is already in progress.
SPINEL_STATUS_ITEM_NOT_FOUND = 20, ///< The given item could not be found.
SPINEL_STATUS_INVALID_COMMAND_FOR_PROP = 21, ///< The given command cannot be performed on this property.
SPINEL_STATUS_RESPONSE_TIMEOUT = 24, ///< No response received from remote node
SPINEL_STATUS_JOIN__BEGIN = 104,
@@ -724,6 +725,13 @@ enum
SPINEL_RADIO_LINK_TREL_UDP6 = 1,
};
// Parameter ids used for:
// @ref SPINEL_PROP_THREAD_MLR_REQUEST
enum
{
SPINEL_THREAD_MLR_PARAMID_TIMEOUT = 0
};
// Backbone Router states used for:
// @ref SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE
enum
@@ -2955,6 +2963,46 @@ enum
*/
SPINEL_PROP_THREAD_DOMAIN_NAME = SPINEL_PROP_THREAD_EXT__BEGIN + 44,
/// Multicast Listeners Register Request
/** Format `t(A(6))A(t(CD))` - Write-only
* Required capability: `SPINEL_CAP_NET_THREAD_1_2`
*
* `t(A(6))`: Array of IPv6 multicast addresses
* `A(t(CD))`: Array of structs holding optional parameters as follows
* `C`: Parameter id
* `D`: Parameter value
*
* +----------------------------------------------------------------+
* | Id: SPINEL_THREAD_MLR_PARAMID_TIMEOUT |
* | Type: `L` |
* | Description: Timeout in seconds. If this optional parameter is |
* | omitted, the default value of the BBR will be used. |
* | Special values: |
* | 0 causes given addresses to be removed |
* | 0xFFFFFFFF is permanent and persistent registration |
* +----------------------------------------------------------------+
*
* Write to this property initiates update of Multicast Listeners Table on the primary BBR.
* If the write succeeded, the result of network operation will be notified later by the
* SPINEL_PROP_THREAD_MLR_RESPONSE property. If the write fails, no MLR.req is issued and
* notifiaction through the SPINEL_PROP_THREAD_MLR_RESPONSE property will not occur.
*
*/
SPINEL_PROP_THREAD_MLR_REQUEST = SPINEL_PROP_THREAD_EXT__BEGIN + 52,
/// Multicast Listeners Register Response
/** Format `CCt(A(6))` - Unsolicited notifications only
* Required capability: `SPINEL_CAP_NET_THREAD_1_2`
*
* `C`: Status
* `C`: MlrStatus (The Multicast Listener Registration Status)
* `A(6)`: Array of IPv6 addresses that failed to be updated on the primary BBR
*
* This property is notified asynchronously when the NCP receives MLR.rsp following
* previous write to the SPINEL_PROP_THREAD_MLR_REQUEST property.
*/
SPINEL_PROP_THREAD_MLR_RESPONSE = SPINEL_PROP_THREAD_EXT__BEGIN + 53,
/// Interface Identifier specified for Thread Domain Unicast Address.
/** Format: `A(C)` - Read-write
*
+4
View File
@@ -135,6 +135,10 @@ spinel_status_t NcpBase::ThreadErrorToSpinelStatus(otError aError)
ret = SPINEL_STATUS_ITEM_NOT_FOUND;
break;
case OT_ERROR_RESPONSE_TIMEOUT:
ret = SPINEL_STATUS_RESPONSE_TIMEOUT;
break;
default:
// Unknown error code. Wrap it as a Spinel status and return that.
ret = static_cast<spinel_status_t>(SPINEL_STATUS_STACK_NATIVE__BEGIN + static_cast<uint32_t>(aError));
+10
View File
@@ -337,6 +337,16 @@ protected:
void HandleJoinerCallback(otError aError);
#endif
static void HandleMlrRegResult_Jump(void * aContext,
otError aError,
uint8_t aMlrStatus,
const otIp6Address *aFailedAddresses,
uint8_t aFailedAddressNum);
void HandleMlrRegResult(otError aError,
uint8_t aMlrStatus,
const otIp6Address *aFailedAddresses,
uint8_t aFailedAddressNum);
otError EncodeOperationalDataset(const otOperationalDataset &aDataset);
otError DecodeOperationalDataset(otOperationalDataset &aDataset,
+3
View File
@@ -554,6 +554,9 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_DOMAIN_NAME),
#endif
#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_MLR_REQUEST),
#endif
#if OPENTHREAD_CONFIG_DUA_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_DUA_ID),
#endif
+88
View File
@@ -262,6 +262,94 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CSL_CHANNEL>(v
}
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MLR_REQUEST>(void)
{
otError error = OT_ERROR_NONE;
otIp6Address addresses[kIPv6AddressesNumMax];
uint8_t addressesCount = 0U;
bool timeoutPresent = false;
uint32_t timeout;
SuccessOrExit(error = mDecoder.OpenStruct());
while (mDecoder.GetRemainingLengthInStruct())
{
VerifyOrExit(addressesCount < kIPv6AddressesNumMax, error = OT_ERROR_NO_BUFS);
SuccessOrExit(error = mDecoder.ReadIp6Address(addresses[addressesCount]));
++addressesCount;
}
SuccessOrExit(error = mDecoder.CloseStruct());
while (mDecoder.GetRemainingLengthInStruct())
{
uint8_t paramId;
SuccessOrExit(error = mDecoder.OpenStruct());
SuccessOrExit(error = mDecoder.ReadUint8(paramId));
switch (paramId)
{
case SPINEL_THREAD_MLR_PARAMID_TIMEOUT:
SuccessOrExit(error = mDecoder.ReadUint32(timeout));
timeoutPresent = true;
break;
default:
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
SuccessOrExit(error = mDecoder.CloseStruct());
}
SuccessOrExit(error = otIp6RegisterMulticastListeners(mInstance, addresses, addressesCount,
timeoutPresent ? &timeout : nullptr,
&NcpBase::HandleMlrRegResult_Jump, this));
exit:
return error;
}
void NcpBase::HandleMlrRegResult_Jump(void * aContext,
otError aError,
uint8_t aMlrStatus,
const otIp6Address *aFailedAddresses,
uint8_t aFailedAddressNum)
{
static_cast<NcpBase *>(aContext)->HandleMlrRegResult(aError, aMlrStatus, aFailedAddresses, aFailedAddressNum);
}
void NcpBase::HandleMlrRegResult(otError aError,
uint8_t aMlrStatus,
const otIp6Address *aFailedAddresses,
uint8_t aFailedAddressNum)
{
SuccessOrExit(mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_IS,
SPINEL_PROP_THREAD_MLR_RESPONSE));
SuccessOrExit(mEncoder.WriteUint8(static_cast<uint8_t>(ThreadErrorToSpinelStatus(aError))));
SuccessOrExit(mEncoder.WriteUint8(aMlrStatus));
SuccessOrExit(mEncoder.OpenStruct());
if (aError == OT_ERROR_NONE)
{
for (size_t i = 0U; i < aFailedAddressNum; ++i)
{
SuccessOrExit(mEncoder.WriteIp6Address(aFailedAddresses[i]));
}
}
SuccessOrExit(mEncoder.CloseStruct());
SuccessOrExit(mEncoder.EndFrame());
exit:
return;
}
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_PRIMARY>(void)
{