diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp index 6de70073c..ca28ef42c 100644 --- a/src/core/meshcop/dataset.cpp +++ b/src/core/meshcop/dataset.cpp @@ -103,57 +103,13 @@ exit: bool Dataset::Info::IsSubsetOf(const Info &aOther) const { - bool isSubset = false; + Dataset dataset; + Dataset other; - if (IsPresent()) - { - VerifyOrExit(aOther.IsPresent() && Get() == aOther.Get()); - } + dataset.SetFrom(*this); + other.SetFrom(aOther); - if (IsPresent()) - { - VerifyOrExit(aOther.IsPresent() && Get() == aOther.Get()); - } - - if (IsPresent()) - { - VerifyOrExit(aOther.IsPresent() && Get() == aOther.Get()); - } - - if (IsPresent()) - { - VerifyOrExit(aOther.IsPresent() && Get() == aOther.Get()); - } - - if (IsPresent()) - { - VerifyOrExit(aOther.IsPresent() && Get() == aOther.Get()); - } - - if (IsPresent()) - { - VerifyOrExit(aOther.IsPresent() && Get() == aOther.Get()); - } - - if (IsPresent()) - { - VerifyOrExit(aOther.IsPresent() && Get() == aOther.Get()); - } - - if (IsPresent()) - { - VerifyOrExit(aOther.IsPresent() && Get() == aOther.Get()); - } - - if (IsPresent()) - { - VerifyOrExit(aOther.IsPresent() && Get() == aOther.Get()); - } - - isSubset = true; - -exit: - return isSubset; + return dataset.IsSubsetOf(other); } Dataset::Dataset(void) @@ -585,6 +541,31 @@ void Dataset::RemoveTlv(Tlv *aTlv) } } +bool Dataset::IsSubsetOf(const Dataset &aOther) const +{ + bool isSubset = false; + + for (const Tlv *tlv = GetTlvsStart(); tlv < GetTlvsEnd(); tlv = tlv->GetNext()) + { + const Tlv *otherTlv; + + if ((tlv->GetType() == Tlv::kActiveTimestamp) || (tlv->GetType() == Tlv::kPendingTimestamp) || + (tlv->GetType() == Tlv::kDelayTimer)) + { + continue; + } + + otherTlv = aOther.FindTlv(tlv->GetType()); + VerifyOrExit(otherTlv != nullptr); + VerifyOrExit(memcmp(tlv, otherTlv, tlv->GetSize()) == 0); + } + + isSubset = true; + +exit: + return isSubset; +} + const char *Dataset::TypeToString(Type aType) { return (aType == kActive) ? "Active" : "Pending"; } #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp index 515d66709..534fbab1b 100644 --- a/src/core/meshcop/dataset.hpp +++ b/src/core/meshcop/dataset.hpp @@ -220,7 +220,7 @@ public: * * @param[in] aOther The other Dataset to check against. * - * @retval TRUE The current dataset is a subset of @p aOther. + * @retval TRUE The current Dataset is a subset of @p aOther. * @retval FALSE The current Dataset is not a subset of @p aOther. * */ @@ -672,6 +672,20 @@ public: */ const Tlv *GetTlvsEnd(void) const { return reinterpret_cast(mTlvs + mLength); } + /** + * Determines whether this Dataset is a subset of another Dataset. + * + * The Dataset is considered a subset if all of its TLVs, excluding Active/Pending Timestamp and Delay Timer TLVs, + * are present in the @p aOther Dataset and the TLV values match exactly. + * + * @param[in] aOther The other Dataset to check against. + * + * @retval TRUE The current dataset is a subset of @p aOther. + * @retval FALSE The current Dataset is not a subset of @p aOther. + * + */ + bool IsSubsetOf(const Dataset &aOther) const; + /** * Converts a Dataset Type to a string. * diff --git a/tests/unit/test_dataset.cpp b/tests/unit/test_dataset.cpp index 88fe2e5d0..3f82b3e6a 100644 --- a/tests/unit/test_dataset.cpp +++ b/tests/unit/test_dataset.cpp @@ -224,6 +224,41 @@ void TestDataset(void) VerifyOrQuit(memcmp(dataset.GetBytes() + sizeof(kTlvBytes), kTlvBytes, sizeof(kTlvBytes)) == 0); VerifyOrQuit(dataset.ValidateTlvs() == kErrorParse); + + // Validate `IsSubsetOf()` + + SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes))); + + datasetInfo.Clear(); + datasetInfo.mComponents.mIsPanIdPresent = true; + datasetInfo.mComponents.mIsNetworkKeyPresent = true; + datasetInfo.mPanId = 0xface; + datasetInfo.mNetworkKey = kNetworkKey; + + dataset2.SetFrom(datasetInfo); + + SuccessOrQuit(dataset2.ValidateTlvs()); + SuccessOrQuit(dataset.ValidateTlvs()); + + VerifyOrQuit(dataset2.IsSubsetOf(dataset)); + VerifyOrQuit(!dataset.IsSubsetOf(dataset2)); + + datasetInfo.mComponents.mIsActiveTimestampPresent = true; + datasetInfo.mComponents.mIsPendingTimestampPresent = true; + datasetInfo.mComponents.mIsDelayPresent = true; + datasetInfo.mActiveTimestamp.mSeconds = 0xffff; + datasetInfo.mPendingTimestamp.mSeconds = 0x1000; + datasetInfo.mDelay = 5000; + dataset2.SetFrom(datasetInfo); + + VerifyOrQuit(dataset2.IsSubsetOf(dataset)); + VerifyOrQuit(!dataset.IsSubsetOf(dataset2)); + + datasetInfo.mPanId = 0xcafe; + dataset2.SetFrom(datasetInfo); + + VerifyOrQuit(!dataset2.IsSubsetOf(dataset)); + VerifyOrQuit(!dataset.IsSubsetOf(dataset2)); } } // namespace MeshCoP