[dataset] add callback to receive MGMT_SET responses (#6887)

This commit is contained in:
jinran-google
2021-08-10 20:12:16 -07:00
committed by GitHub
parent c494b9f25d
commit 71bc37bbc3
10 changed files with 133 additions and 38 deletions
+27 -2
View File
@@ -290,6 +290,21 @@ typedef enum otMeshcopTlvType
OT_MESHCOP_TLV_JOINERADVERTISEMENT = 241, ///< meshcop Joiner Advertisement TLV
} otMeshcopTlvType;
/**
* This function pointer is called when a response to a MGMT_SET request is received or times out.
*
* @param[in] aResult A result of the operation.
* @param[in] aContext A pointer to application-specific context.
*
* @retval OT_ERROR_NONE The request was accepted by the leader.
* @retval OT_ERROR_REJECTED The request was rejected by the leader.
* @retval OT_ERROR_PARSE An error occurred during parsing the response.
* @retval OT_ERROR_ABORT The request was reset by peer.
* @retval OT_ERROR_RESPONSE_TIMEOUT No response or acknowledgment received during timeout period.
*
*/
typedef void (*otDatasetMgmtSetCallback)(otError aResult, void *aContext);
/**
* This function indicates whether a valid network is present in the Active Operational Dataset or not.
*
@@ -452,15 +467,20 @@ otError otDatasetSendMgmtActiveGet(otInstance * aInstan
* @param[in] aDataset A pointer to operational dataset.
* @param[in] aTlvs A pointer to TLVs.
* @param[in] aLength The length of TLVs.
* @param[in] aCallback A pointer to a function that is called on response reception or timeout.
* @param[in] aContext A pointer to application-specific context for @p aCallback.
*
* @retval OT_ERROR_NONE Successfully send the meshcop dataset command.
* @retval OT_ERROR_NO_BUFS Insufficient buffer space to send.
* @retval OT_ERROR_BUSY A previous request is ongoing.
*
*/
otError otDatasetSendMgmtActiveSet(otInstance * aInstance,
const otOperationalDataset *aDataset,
const uint8_t * aTlvs,
uint8_t aLength);
uint8_t aLength,
otDatasetMgmtSetCallback aCallback,
void * aContext);
/**
* This function sends MGMT_PENDING_GET.
@@ -488,15 +508,20 @@ otError otDatasetSendMgmtPendingGet(otInstance * aInsta
* @param[in] aDataset A pointer to operational dataset.
* @param[in] aTlvs A pointer to TLVs.
* @param[in] aLength The length of TLVs.
* @param[in] aCallback A pointer to a function that is called on response reception or timeout.
* @param[in] aContext A pointer to application-specific context for @p aCallback.
*
* @retval OT_ERROR_NONE Successfully send the meshcop dataset command.
* @retval OT_ERROR_NO_BUFS Insufficient buffer space to send.
* @retval OT_ERROR_BUSY A previous request is ongoing.
*
*/
otError otDatasetSendMgmtPendingSet(otInstance * aInstance,
const otOperationalDataset *aDataset,
const uint8_t * aTlvs,
uint8_t aLength);
uint8_t aLength,
otDatasetMgmtSetCallback aCallback,
void * aContext);
/**
* This function generates PSKc from a given pass-phrase, network name, and extended PAN ID.
+5
View File
@@ -234,6 +234,11 @@ typedef enum OT_MUST_USE_RESULT otError
*/
OT_ERROR_PENDING = 36,
/**
* Request rejected.
*/
OT_ERROR_REJECTED = 37,
/**
* The number of defined errors.
*/
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (145)
#define OPENTHREAD_API_VERSION (146)
/**
* @addtogroup api-instance
+4 -2
View File
@@ -565,11 +565,13 @@ otError Dataset::ProcessMgmtSetCommand(Arg aArgs[])
if (aArgs[0] == "active")
{
error = otDatasetSendMgmtActiveSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength);
error = otDatasetSendMgmtActiveSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength, /* aCallback */ nullptr,
/* aContext */ nullptr);
}
else if (aArgs[0] == "pending")
{
error = otDatasetSendMgmtPendingSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength);
error = otDatasetSendMgmtPendingSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength, /* aCallback */ nullptr,
/* aContext */ nullptr);
}
else
{
+8 -4
View File
@@ -136,12 +136,14 @@ otError otDatasetSendMgmtActiveGet(otInstance * aInstan
otError otDatasetSendMgmtActiveSet(otInstance * aInstance,
const otOperationalDataset *aDataset,
const uint8_t * aTlvs,
uint8_t aLength)
uint8_t aLength,
otDatasetMgmtSetCallback aCallback,
void * aContext)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<MeshCoP::ActiveDataset>().SendSetRequest(*static_cast<const MeshCoP::Dataset::Info *>(aDataset),
aTlvs, aLength);
aTlvs, aLength, aCallback, aContext);
}
otError otDatasetSendMgmtPendingGet(otInstance * aInstance,
@@ -159,12 +161,14 @@ otError otDatasetSendMgmtPendingGet(otInstance * aInsta
otError otDatasetSendMgmtPendingSet(otInstance * aInstance,
const otOperationalDataset *aDataset,
const uint8_t * aTlvs,
uint8_t aLength)
uint8_t aLength,
otDatasetMgmtSetCallback aCallback,
void * aContext)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<MeshCoP::PendingDataset>().SendSetRequest(
*static_cast<const MeshCoP::Dataset::Info *>(aDataset), aTlvs, aLength);
*static_cast<const MeshCoP::Dataset::Info *>(aDataset), aTlvs, aLength, aCallback, aContext);
}
#if OPENTHREAD_FTD
+1
View File
@@ -77,6 +77,7 @@ const char *ErrorToString(Error aError)
"LinkMarginLow", // (34) kErrorLinkMarginLow
"InvalidCommand", // (35) kErrorInvalidCommand
"Pending", // (36) kErrorPending
"Rejected", // (37) kErrorRejected
};
return aError < OT_ARRAY_LENGTH(kErrorStrings) ? kErrorStrings[aError] : "UnknownErrorType";
+1
View File
@@ -88,6 +88,7 @@ constexpr Error kErrorNotLowpanDataFrame = OT_ERROR_NOT_LOWPAN_DATA_FRAM
constexpr Error kErrorLinkMarginLow = OT_ERROR_LINK_MARGIN_LOW;
constexpr Error kErrorInvalidCommand = OT_ERROR_INVALID_COMMAND;
constexpr Error kErrorPending = OT_ERROR_PENDING;
constexpr Error kErrorRejected = OT_ERROR_REJECTED;
constexpr Error kErrorGeneric = OT_ERROR_GENERIC;
constexpr uint8_t kNumErrors = OT_NUM_ERRORS;
+65 -20
View File
@@ -54,8 +54,10 @@ DatasetManager::DatasetManager(Instance &aInstance, Dataset::Type aType, Timer::
: InstanceLocator(aInstance)
, mLocal(aInstance, aType)
, mTimestampValid(false)
, mCoapPending(false)
, mMgmtPending(false)
, mTimer(aInstance, aTimerHandler)
, mMgmtSetCallback(nullptr)
, mMgmtSetCallbackContext(nullptr)
{
mTimestamp.Init();
}
@@ -277,7 +279,7 @@ void DatasetManager::SendSet(void)
Ip6::MessageInfo messageInfo;
Dataset dataset;
VerifyOrExit(!mCoapPending, error = kErrorBusy);
VerifyOrExit(!mMgmtPending, error = kErrorBusy);
VerifyOrExit(Get<Mle::MleRouter>().IsChild() || Get<Mle::MleRouter>().IsRouter(), error = kErrorInvalidState);
VerifyOrExit(mLocal.Compare(GetTimestamp()) < 0, error = kErrorInvalidState);
@@ -308,8 +310,8 @@ void DatasetManager::SendSet(void)
messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
IgnoreError(Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
messageInfo.SetPeerPort(Tmf::kUdpPort);
SuccessOrExit(error =
Get<Tmf::Agent>().SendMessage(*message, messageInfo, &DatasetManager::HandleCoapResponse, this));
SuccessOrExit(
error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, &DatasetManager::HandleMgmtSetResponse, this));
otLogInfoMeshCoP("Sent %s set to leader", Dataset::TypeToString(GetType()));
@@ -318,7 +320,7 @@ exit:
switch (error)
{
case kErrorNone:
mCoapPending = true;
mMgmtPending = true;
break;
case kErrorNoBufs:
@@ -332,21 +334,54 @@ exit:
}
}
void DatasetManager::HandleCoapResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
Error aError)
void DatasetManager::HandleMgmtSetResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
Error aError)
{
OT_UNUSED_VARIABLE(aMessage);
OT_UNUSED_VARIABLE(aMessageInfo);
OT_UNUSED_VARIABLE(aError);
static_cast<DatasetManager *>(aContext)->HandleCoapResponse();
static_cast<DatasetManager *>(aContext)->HandleMgmtSetResponse(
*static_cast<Coap::Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo), aError);
}
void DatasetManager::HandleCoapResponse(void)
void DatasetManager::HandleMgmtSetResponse(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Error aError)
{
mCoapPending = false;
OT_UNUSED_VARIABLE(aMessageInfo);
Error error;
StateTlv stateTlv;
SuccessOrExit(error = aError);
VerifyOrExit(Tlv::FindTlv(aMessage, stateTlv) == kErrorNone, error = kErrorParse);
switch (stateTlv.GetState())
{
case StateTlv::kReject:
error = kErrorRejected;
break;
case StateTlv::kAccept:
error = kErrorNone;
break;
default:
error = kErrorParse;
break;
}
exit:
otLogInfoMeshCoP("MGMT_SET finished: %s", ErrorToString(error));
mMgmtPending = false;
if (mMgmtSetCallback != nullptr)
{
otDatasetMgmtSetCallback callback = mMgmtSetCallback;
void * context = mMgmtSetCallbackContext;
mMgmtSetCallback = nullptr;
mMgmtSetCallbackContext = nullptr;
callback(error, context);
}
mTimer.Start(kSendSetDelay);
}
@@ -460,12 +495,18 @@ exit:
return error;
}
Error DatasetManager::SendSetRequest(const Dataset::Info &aDatasetInfo, const uint8_t *aTlvs, uint8_t aLength)
Error DatasetManager::SendSetRequest(const Dataset::Info & aDatasetInfo,
const uint8_t * aTlvs,
uint8_t aLength,
otDatasetMgmtSetCallback aCallback,
void * aContext)
{
Error error = kErrorNone;
Coap::Message * message;
Error error = kErrorNone;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
VerifyOrExit(!mMgmtPending, error = kErrorBusy);
VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error =
@@ -508,7 +549,11 @@ Error DatasetManager::SendSetRequest(const Dataset::Info &aDatasetInfo, const ui
messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
IgnoreError(Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
messageInfo.SetPeerPort(Tmf::kUdpPort);
SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, HandleMgmtSetResponse, this));
mMgmtSetCallback = aCallback;
mMgmtSetCallbackContext = aContext;
mMgmtPending = true;
otLogInfoMeshCoP("sent dataset set request to leader");
+17 -7
View File
@@ -149,12 +149,19 @@ public:
* @param[in] aDatasetInfo The Operational Dataset.
* @param[in] aTlvs Any additional raw TLVs to include.
* @param[in] aLength Number of bytes in @p aTlvs.
* @param[in] aCallback A pointer to a function that is called on response reception or timeout.
* @param[in] aContext A pointer to application-specific context for @p aCallback.
*
* @retval kErrorNone Successfully send the meshcop dataset command.
* @retval kErrorNoBufs Insufficient buffer space to send.
* @retval kErrorBusy A previous request is ongoing.
*
*/
Error SendSetRequest(const Dataset::Info &aDatasetInfo, const uint8_t *aTlvs, uint8_t aLength);
Error SendSetRequest(const Dataset::Info & aDatasetInfo,
const uint8_t * aTlvs,
uint8_t aLength,
otDatasetMgmtSetCallback aCallback,
void * aContext);
/**
* This method sends a MGMT_GET request.
@@ -334,11 +341,11 @@ protected:
bool mTimestampValid : 1;
private:
static void HandleCoapResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
Error aError);
void HandleCoapResponse(void);
static void HandleMgmtSetResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
Error aError);
void HandleMgmtSetResponse(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Error aError);
bool IsActiveDataset(void) const { return GetType() == Dataset::kActive; }
bool IsPendingDataset(void) const { return GetType() == Dataset::kPending; }
@@ -358,8 +365,11 @@ private:
static constexpr uint8_t kMaxDatasetTlvs = 16; // Maximum number of TLVs in a Dataset.
static constexpr uint32_t kSendSetDelay = 5000; // Milliseconds
bool mCoapPending : 1;
bool mMgmtPending : 1;
TimerMilli mTimer;
otDatasetMgmtSetCallback mMgmtSetCallback;
void * mMgmtSetCallbackContext;
};
class ActiveDataset : public DatasetManager, private NonCopyable
+4 -2
View File
@@ -1672,7 +1672,8 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_SET_ACTIV
uint8_t extraTlvsLength;
SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength));
error = otDatasetSendMgmtActiveSet(mInstance, &dataset, extraTlvs, extraTlvsLength);
error = otDatasetSendMgmtActiveSet(mInstance, &dataset, extraTlvs, extraTlvsLength, /* aCallback */ nullptr,
/* aContext */ nullptr);
exit:
return error;
@@ -1686,7 +1687,8 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_SET_PENDI
uint8_t extraTlvsLength;
SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength));
error = otDatasetSendMgmtPendingSet(mInstance, &dataset, extraTlvs, extraTlvsLength);
error = otDatasetSendMgmtPendingSet(mInstance, &dataset, extraTlvs, extraTlvsLength, /* aCallback */ nullptr,
/* aContext */ nullptr);
exit:
return error;