[mle] fix bug in leader active/pending dataset synchronization (#5021)

The leader is the authoritative source when propagating active/pending
operational datasets. When the leader reboots, it is possible for the
leader to become out-of-sync. In particular, after the leader resets,
it restores its network data and active/pending operational datasets
using MLE Data Request/Response to retrieve them from a neighboring
device. If the neighboring device has an older active/pending
operational dataset, the leader will retrieve the older datasets and
never attempt to propagate the newer datasets that it may have stored
locally.

This commit makes the following changes:

- The leader does not accept any changes to the active/pending
  operational datasets.

- After retrieving the latest network data from a neighboring device
  (as part of resynchronizing after reset), the leader will increment
  the full and stable network data versions to ensure that the leader
  propagates the latest active/pending operational datasets.
This commit is contained in:
Jonathan Hui
2020-05-29 17:01:46 -07:00
committed by GitHub
parent 46305be082
commit b0b2591bc0
+26 -17
View File
@@ -3024,7 +3024,7 @@ otError Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &a
// if received timestamp does not match the local value and message does not contain the dataset,
// send MLE Data Request
if ((timestamp == NULL || timestamp->Compare(activeTimestamp) != 0) &&
if (!IsLeader() && ((timestamp == NULL) || (timestamp->Compare(activeTimestamp) != 0)) &&
(Tlv::FindTlvOffset(aMessage, Tlv::kActiveDataset, activeDatasetOffset) != OT_ERROR_NONE))
{
ExitNow(dataRequest = true);
@@ -3045,7 +3045,7 @@ otError Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &a
// if received timestamp does not match the local value and message does not contain the dataset,
// send MLE Data Request
if ((timestamp == NULL || timestamp->Compare(pendingTimestamp) != 0) &&
if (!IsLeader() && ((timestamp == NULL) || (timestamp->Compare(pendingTimestamp) != 0)) &&
(Tlv::FindTlvOffset(aMessage, Tlv::kPendingDataset, pendingDatasetOffset) != OT_ERROR_NONE))
{
ExitNow(dataRequest = true);
@@ -3068,25 +3068,34 @@ otError Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &a
ExitNow(dataRequest = true);
}
// Active Dataset
if (activeTimestamp.GetLength() > 0)
#if OPENTHREAD_FTD
if (IsLeader())
{
if (activeDatasetOffset > 0)
{
aMessage.Read(activeDatasetOffset, sizeof(tlv), &tlv);
IgnoreError(Get<MeshCoP::ActiveDataset>().Save(activeTimestamp, aMessage, activeDatasetOffset + sizeof(tlv),
tlv.GetLength()));
}
Get<NetworkData::Leader>().IncrementVersionAndStableVersion();
}
// Pending Dataset
if (pendingTimestamp.GetLength() > 0)
else
#endif
{
if (pendingDatasetOffset > 0)
// Active Dataset
if (activeTimestamp.GetLength() > 0)
{
aMessage.Read(pendingDatasetOffset, sizeof(tlv), &tlv);
IgnoreError(Get<MeshCoP::PendingDataset>().Save(pendingTimestamp, aMessage,
pendingDatasetOffset + sizeof(tlv), tlv.GetLength()));
if (activeDatasetOffset > 0)
{
aMessage.Read(activeDatasetOffset, sizeof(tlv), &tlv);
IgnoreError(Get<MeshCoP::ActiveDataset>().Save(activeTimestamp, aMessage,
activeDatasetOffset + sizeof(tlv), tlv.GetLength()));
}
}
// Pending Dataset
if (pendingTimestamp.GetLength() > 0)
{
if (pendingDatasetOffset > 0)
{
aMessage.Read(pendingDatasetOffset, sizeof(tlv), &tlv);
IgnoreError(Get<MeshCoP::PendingDataset>().Save(pendingTimestamp, aMessage,
pendingDatasetOffset + sizeof(tlv), tlv.GetLength()));
}
}
}