[meshcop] do not send MGMT_*_SET.req while one is outstanding (#4981)

This commit helps ensure the following:

- At most one MGMT_ACTIVE_SET.req message is outstanding.

- At most one MGMT_PENDING_SET.req message is outstanding.
This commit is contained in:
Jonathan Hui
2020-05-20 14:27:41 -07:00
committed by GitHub
parent 883d32356f
commit 2485f72d15
2 changed files with 74 additions and 35 deletions
+59 -29
View File
@@ -60,6 +60,7 @@ DatasetManager::DatasetManager(Instance & aInstance,
, mTimer(aInstance, aTimerHandler, this)
, mUriGet(aUriGet)
, mUriSet(aUriSet)
, mCoapPending(false)
{
mTimestamp.Init();
}
@@ -168,7 +169,7 @@ otError DatasetManager::Save(const Dataset &aDataset)
}
else if (compare < 0)
{
mTimer.Start(1000);
SendSet();
}
exit:
@@ -188,11 +189,11 @@ otError DatasetManager::Save(const otOperationalDataset &aDataset)
break;
case Mle::kRoleChild:
mTimer.Start(1000);
SendSet();
break;
#if OPENTHREAD_FTD
case Mle::kRoleRouter:
mTimer.Start(1000);
SendSet();
break;
case Mle::kRoleLeader:
@@ -232,39 +233,35 @@ exit:
void DatasetManager::HandleTimer(void)
{
VerifyOrExit(Get<Mle::MleRouter>().IsAttached(), OT_NOOP);
SendSet();
}
VerifyOrExit(mLocal.Compare(GetTimestamp()) < 0, OT_NOOP);
void DatasetManager::SendSet(void)
{
otError error;
Coap::Message * message = NULL;
Ip6::MessageInfo messageInfo;
Dataset dataset(mLocal.GetType());
VerifyOrExit(!mCoapPending, error = OT_ERROR_BUSY);
VerifyOrExit(Get<Mle::MleRouter>().IsAttached(), error = OT_ERROR_INVALID_STATE);
VerifyOrExit(mLocal.Compare(GetTimestamp()) < 0, error = OT_ERROR_INVALID_STATE);
if (mLocal.GetType() == Dataset::kActive)
{
Dataset dataset(Dataset::kPending);
IgnoreError(Get<PendingDataset>().Read(dataset));
Dataset pendingDataset(Dataset::kPending);
IgnoreError(Get<PendingDataset>().Read(pendingDataset));
const ActiveTimestampTlv *tlv = dataset.GetTlv<ActiveTimestampTlv>();
const ActiveTimestampTlv *tlv = pendingDataset.GetTlv<ActiveTimestampTlv>();
const Timestamp * pendingActiveTimestamp = static_cast<const Timestamp *>(tlv);
if (pendingActiveTimestamp != NULL && mLocal.Compare(pendingActiveTimestamp) == 0)
{
// stop registration attempts during dataset transition
ExitNow();
ExitNow(error = OT_ERROR_INVALID_STATE);
}
}
IgnoreError(Register());
mTimer.Start(1000);
exit:
return;
}
otError DatasetManager::Register(void)
{
otError error = OT_ERROR_NONE;
Coap::Message * message;
Ip6::MessageInfo messageInfo;
Dataset dataset(mLocal.GetType());
VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::Coap>())) != NULL, error = OT_ERROR_NO_BUFS);
SuccessOrExit(error = message->Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST, mUriSet));
@@ -276,18 +273,51 @@ otError DatasetManager::Register(void)
messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
IgnoreError(Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
messageInfo.SetPeerPort(kCoapUdpPort);
SuccessOrExit(error = Get<Coap::Coap>().SendMessage(*message, messageInfo));
SuccessOrExit(error =
Get<Coap::Coap>().SendMessage(*message, messageInfo, &DatasetManager::HandleCoapResponse, this));
otLogInfoMeshCoP("sent dataset to leader");
otLogInfoMeshCoP("Sent %s to leader", mUriSet);
exit:
if (error != OT_ERROR_NONE && message != NULL)
switch (error)
{
message->Free();
}
case OT_ERROR_NONE:
mCoapPending = true;
break;
return error;
case OT_ERROR_NO_BUFS:
mTimer.Start(kDelayNoBufs);
// fall through
default:
otLogWarnMeshCoP("Failed to send %s to leader: %s", mUriSet, otThreadErrorToString(error));
if (message != NULL)
{
message->Free();
}
break;
}
}
void DatasetManager::HandleCoapResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
otError aError)
{
OT_UNUSED_VARIABLE(aMessage);
OT_UNUSED_VARIABLE(aMessageInfo);
OT_UNUSED_VARIABLE(aError);
static_cast<DatasetManager *>(aContext)->HandleCoapResponse();
}
void DatasetManager::HandleCoapResponse(void)
{
mCoapPending = false;
SendSet();
}
void DatasetManager::HandleGet(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
+15 -6
View File
@@ -278,15 +278,22 @@ private:
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleUdpReceive(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
otError Register(void);
void SendGetResponse(const Coap::Message & aRequest,
const Ip6::MessageInfo &aMessageInfo,
uint8_t * aTlvs,
uint8_t aLength) const;
static void HandleCoapResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
otError aError);
void HandleCoapResponse(void);
void SendSet(void);
void SendGetResponse(const Coap::Message & aRequest,
const Ip6::MessageInfo &aMessageInfo,
uint8_t * aTlvs,
uint8_t aLength) const;
enum
{
kMaxDatasetTlvs = 16, // Maximum number of TLVs in an `otOperationalDataset`.
kMaxDatasetTlvs = 16, // Maximum number of TLVs in an `otOperationalDataset`.
kDelayNoBufs = 1000, // Milliseconds
};
TimerMilli mTimer;
@@ -294,6 +301,8 @@ private:
const char *mUriGet;
const char *mUriSet;
bool mCoapPending : 1;
#if OPENTHREAD_FTD
public:
/**