mirror of
https://github.com/espressif/openthread.git
synced 2026-08-13 06:07:48 +00:00
[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:
@@ -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),
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user