[dataset] simplify IsSubsetOf() (#10292)

This commit adds a method `Dataset::IsSubsetOf()` to check whether one
dataset is a subset of another. A dataset is considered a subset if
all its TLVs, excluding Active/Pending Timestamp and Delay Timer
TLVs, are present in the other dataset with exactly matching values.

This new method simplifies `Dataset::Info::IsSubsetOf()`. The unit
test `test_dataset` is updated to validate the `IsSubsetOf()()`
method.
This commit is contained in:
Abtin Keshavarzian
2024-05-24 20:18:37 -07:00
committed by GitHub
parent 0abc8d7a0d
commit a54f4c4850
3 changed files with 80 additions and 50 deletions
+30 -49
View File
@@ -103,57 +103,13 @@ exit:
bool Dataset::Info::IsSubsetOf(const Info &aOther) const
{
bool isSubset = false;
Dataset dataset;
Dataset other;
if (IsPresent<kNetworkKey>())
{
VerifyOrExit(aOther.IsPresent<kNetworkKey>() && Get<kNetworkKey>() == aOther.Get<kNetworkKey>());
}
dataset.SetFrom(*this);
other.SetFrom(aOther);
if (IsPresent<kNetworkName>())
{
VerifyOrExit(aOther.IsPresent<kNetworkName>() && Get<kNetworkName>() == aOther.Get<kNetworkName>());
}
if (IsPresent<kExtendedPanId>())
{
VerifyOrExit(aOther.IsPresent<kExtendedPanId>() && Get<kExtendedPanId>() == aOther.Get<kExtendedPanId>());
}
if (IsPresent<kMeshLocalPrefix>())
{
VerifyOrExit(aOther.IsPresent<kMeshLocalPrefix>() && Get<kMeshLocalPrefix>() == aOther.Get<kMeshLocalPrefix>());
}
if (IsPresent<kPanId>())
{
VerifyOrExit(aOther.IsPresent<kPanId>() && Get<kPanId>() == aOther.Get<kPanId>());
}
if (IsPresent<kChannel>())
{
VerifyOrExit(aOther.IsPresent<kChannel>() && Get<kChannel>() == aOther.Get<kChannel>());
}
if (IsPresent<kPskc>())
{
VerifyOrExit(aOther.IsPresent<kPskc>() && Get<kPskc>() == aOther.Get<kPskc>());
}
if (IsPresent<kSecurityPolicy>())
{
VerifyOrExit(aOther.IsPresent<kSecurityPolicy>() && Get<kSecurityPolicy>() == aOther.Get<kSecurityPolicy>());
}
if (IsPresent<kChannelMask>())
{
VerifyOrExit(aOther.IsPresent<kChannelMask>() && Get<kChannelMask>() == aOther.Get<kChannelMask>());
}
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
+15 -1
View File
@@ -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<const Tlv *>(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.
*
+35
View File
@@ -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