From 7baefe62ed9815e84ea8bcb474464059e4d21e8d Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 15 Apr 2020 10:22:10 -0700 Subject: [PATCH] [network-data] define and use a common Iterate method for all entry types (#4830) This commit adds a common private `Iterate()` method which is used by other methods iterating over different types of entries: `GetNextOnMeshPrefix()`, `GetNextExternalRoute()`, `GetNextService()`, and `GetNextServer()`. It also adds methods to help advancing the iterator to next TLV or sub-TLV or entry index. --- src/core/thread/network_data.cpp | 399 +++++++++++++++---------------- src/core/thread/network_data.hpp | 92 ++++--- 2 files changed, 241 insertions(+), 250 deletions(-) diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp index 543a3583a..1d21317b8 100644 --- a/src/core/thread/network_data.cpp +++ b/src/core/thread/network_data.cpp @@ -104,67 +104,6 @@ exit: return tlv; } -const NetworkDataTlv *NetworkData::FindTlv(NetworkDataIterator &aIterator, NetworkDataTlv::Type aTlvType) const -{ - const NetworkDataTlv *start = aIterator.GetTlv(mTlvs); - const NetworkDataTlv *tlv; - - tlv = FindTlv(start, GetTlvsEnd(), aTlvType); - VerifyOrExit(tlv != NULL); - - if (tlv != start) - { - aIterator.SaveTlvOffset(tlv, mTlvs); - aIterator.SetSubTlvOffset(0); - aIterator.SetEntryIndex(0); - } - -exit: - return tlv; -} - -void NetworkData::IterateToNextTlv(NetworkDataIterator &aIterator) const -{ - const NetworkDataTlv *tlv = aIterator.GetTlv(mTlvs); - - tlv = tlv->GetNext(); - - aIterator.SaveTlvOffset(tlv, mTlvs); - aIterator.SetSubTlvOffset(0); - aIterator.SetEntryIndex(0); -} - -const NetworkDataTlv *NetworkData::FindSubTlv(NetworkDataIterator & aIterator, - NetworkDataTlv::Type aSubTlvType, - const NetworkDataTlv *aSubTlvs, - const NetworkDataTlv *aSubTlvsEnd) const -{ - const NetworkDataTlv *subStart = aIterator.GetSubTlv(aSubTlvs); - const NetworkDataTlv *subTlv; - - subTlv = FindTlv(subStart, aSubTlvsEnd, aSubTlvType); - VerifyOrExit(subTlv != NULL); - - if (subTlv != subStart) - { - aIterator.SaveSubTlvOffset(subTlv, aSubTlvs); - aIterator.SetEntryIndex(0); - } - -exit: - return subTlv; -} - -void NetworkData::IterateToNextSubTlv(NetworkDataIterator &aIterator, const NetworkDataTlv *aSubTlvs) const -{ - const NetworkDataTlv *subTlv = aIterator.GetSubTlv(aSubTlvs); - - subTlv = subTlv->GetNext(); - - aIterator.SaveSubTlvOffset(subTlv, aSubTlvs); - aIterator.SetEntryIndex(0); -} - otError NetworkData::GetNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLength) const { otError error = OT_ERROR_NONE; @@ -191,46 +130,13 @@ otError NetworkData::GetNextOnMeshPrefix(Iterator &aIterator, OnMeshPrefixConfig otError NetworkData::GetNextOnMeshPrefix(Iterator &aIterator, uint16_t aRloc16, OnMeshPrefixConfig &aConfig) const { - otError error = OT_ERROR_NOT_FOUND; - NetworkDataIterator iterator(aIterator); + Config config; - for (const PrefixTlv *prefix; (prefix = FindTlv(iterator)) != NULL; IterateToNextTlv(iterator)) - { - for (const BorderRouterTlv *borderRouter; - (borderRouter = FindSubTlv(iterator, prefix->GetSubTlvs(), prefix->GetNext())) != NULL; - IterateToNextSubTlv(iterator, prefix->GetSubTlvs())) - { - for (uint8_t index = iterator.GetEntryIndex(); index < borderRouter->GetNumEntries(); index++) - { - if (aRloc16 == Mac::kShortAddrBroadcast || borderRouter->GetEntry(index)->GetRloc() == aRloc16) - { - const BorderRouterEntry *borderRouterEntry = borderRouter->GetEntry(index); + config.mOnMeshPrefix = &aConfig; + config.mExternalRoute = NULL; + config.mService = NULL; - memset(&aConfig, 0, sizeof(aConfig)); - memcpy(&aConfig.mPrefix.mPrefix, prefix->GetPrefix(), BitVectorBytes(prefix->GetPrefixLength())); - aConfig.mPrefix.mLength = prefix->GetPrefixLength(); - aConfig.mPreference = borderRouterEntry->GetPreference(); - aConfig.mPreferred = borderRouterEntry->IsPreferred(); - aConfig.mSlaac = borderRouterEntry->IsSlaac(); - aConfig.mDhcp = borderRouterEntry->IsDhcp(); - aConfig.mConfigure = borderRouterEntry->IsConfigure(); - aConfig.mDefaultRoute = borderRouterEntry->IsDefaultRoute(); - aConfig.mOnMesh = borderRouterEntry->IsOnMesh(); - aConfig.mStable = borderRouter->IsStable(); - aConfig.mRloc16 = borderRouterEntry->GetRloc(); - aConfig.mNdDns = borderRouterEntry->IsNdDns(); - aConfig.mDp = borderRouterEntry->IsDp(); - - iterator.SetEntryIndex(index + 1); - - ExitNow(error = OT_ERROR_NONE); - } - } - } - } - -exit: - return error; + return Iterate(aIterator, aRloc16, config); } otError NetworkData::GetNextExternalRoute(Iterator &aIterator, ExternalRouteConfig &aConfig) const @@ -240,39 +146,13 @@ otError NetworkData::GetNextExternalRoute(Iterator &aIterator, ExternalRouteConf otError NetworkData::GetNextExternalRoute(Iterator &aIterator, uint16_t aRloc16, ExternalRouteConfig &aConfig) const { - otError error = OT_ERROR_NOT_FOUND; - NetworkDataIterator iterator(aIterator); + Config config; - for (const PrefixTlv *prefix; (prefix = FindTlv(iterator)) != NULL; IterateToNextTlv(iterator)) - { - for (const HasRouteTlv *hasRoute; - (hasRoute = FindSubTlv(iterator, prefix->GetSubTlvs(), prefix->GetNext())) != NULL; - IterateToNextSubTlv(iterator, prefix->GetSubTlvs())) - { - for (uint8_t index = iterator.GetEntryIndex(); index < hasRoute->GetNumEntries(); index++) - { - if (aRloc16 == Mac::kShortAddrBroadcast || hasRoute->GetEntry(index)->GetRloc() == aRloc16) - { - const HasRouteEntry *hasRouteEntry = hasRoute->GetEntry(index); + config.mOnMeshPrefix = NULL; + config.mExternalRoute = &aConfig; + config.mService = NULL; - memset(&aConfig, 0, sizeof(aConfig)); - memcpy(&aConfig.mPrefix.mPrefix, prefix->GetPrefix(), BitVectorBytes(prefix->GetPrefixLength())); - aConfig.mPrefix.mLength = prefix->GetPrefixLength(); - aConfig.mPreference = hasRouteEntry->GetPreference(); - aConfig.mStable = hasRoute->IsStable(); - aConfig.mRloc16 = hasRouteEntry->GetRloc(); - aConfig.mNextHopIsThisDevice = (hasRouteEntry->GetRloc() == Get().GetRloc16()); - - iterator.SetEntryIndex(index + 1); - - ExitNow(error = OT_ERROR_NONE); - } - } - } - } - -exit: - return error; + return Iterate(aIterator, aRloc16, config); } otError NetworkData::GetNextService(Iterator &aIterator, ServiceConfig &aConfig) const @@ -282,38 +162,183 @@ otError NetworkData::GetNextService(Iterator &aIterator, ServiceConfig &aConfig) otError NetworkData::GetNextService(Iterator &aIterator, uint16_t aRloc16, ServiceConfig &aConfig) const { + Config config; + + config.mOnMeshPrefix = NULL; + config.mExternalRoute = NULL; + config.mService = &aConfig; + + return Iterate(aIterator, aRloc16, config); +} + +otError NetworkData::Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aConfig) const +{ + // Iterate to the next entry in Network Data matching `aRloc16` + // (can be set to `Mac::kShortAddrBroadcast` to allow any RLOC). + // The `aIterator` is used to track and save the current position. + // On input, the non-NULL pointer members in `aConfig` specify the + // Network Data entry types (`mOnMeshPrefix`, `mExternalRoute`, + // `mService`) to iterate over. On successful exit, the `aConfig` + // is updated such that only one member pointer is not NULL + // indicating the type of entry and the non-NULL config is updated + // with the entry info. + otError error = OT_ERROR_NOT_FOUND; NetworkDataIterator iterator(aIterator); - for (const ServiceTlv *service; (service = FindTlv(iterator)) != NULL; IterateToNextTlv(iterator)) + for (const NetworkDataTlv *cur; (cur = iterator.GetTlv(mTlvs)) < GetTlvsEnd(); iterator.AdvanceTlv(mTlvs)) { - for (const ServerTlv *server; - (server = FindSubTlv(iterator, service->GetSubTlvs(), service->GetNext())) != NULL; - IterateToNextSubTlv(iterator, service->GetSubTlvs())) + const NetworkDataTlv *subTlvs = NULL; + + switch (cur->GetType()) { - if (!iterator.IsNewEntry()) + case NetworkDataTlv::kTypePrefix: + if ((aConfig.mOnMeshPrefix != NULL) || (aConfig.mExternalRoute != NULL)) { - continue; + subTlvs = static_cast(cur)->GetSubTlvs(); } - - if ((aRloc16 == Mac::kShortAddrBroadcast) || (server->GetServer16() == aRloc16)) + break; + case NetworkDataTlv::kTypeService: + if (aConfig.mService != NULL) { - memset(&aConfig, 0, sizeof(aConfig)); + subTlvs = static_cast(cur)->GetSubTlvs(); + } + break; + default: + break; + } - aConfig.mServiceId = service->GetServiceId(); - aConfig.mEnterpriseNumber = service->GetEnterpriseNumber(); - aConfig.mServiceDataLength = service->GetServiceDataLength(); + if (subTlvs == NULL) + { + continue; + } - memcpy(&aConfig.mServiceData, service->GetServiceData(), service->GetServiceDataLength()); + for (const NetworkDataTlv *subCur; (subCur = iterator.GetSubTlv(subTlvs)) < cur->GetNext(); + iterator.AdvaceSubTlv(subTlvs)) + { + if (cur->GetType() == NetworkDataTlv::kTypePrefix) + { + const PrefixTlv *prefix = static_cast(cur); - aConfig.mServerConfig.mStable = server->IsStable(); - aConfig.mServerConfig.mServerDataLength = server->GetServerDataLength(); - memcpy(&aConfig.mServerConfig.mServerData, server->GetServerData(), server->GetServerDataLength()); - aConfig.mServerConfig.mRloc16 = server->GetServer16(); + switch (subCur->GetType()) + { + case NetworkDataTlv::kTypeBorderRouter: + { + const BorderRouterTlv *borderRouter = static_cast(subCur); - iterator.MarkEntryAsNotNew(); + if (aConfig.mOnMeshPrefix == NULL) + { + continue; + } - ExitNow(error = OT_ERROR_NONE); + for (uint8_t index; (index = iterator.GetAndAdvanceIndex()) < borderRouter->GetNumEntries();) + { + if (aRloc16 == Mac::kShortAddrBroadcast || borderRouter->GetEntry(index)->GetRloc() == aRloc16) + { + const BorderRouterEntry *borderRouterEntry = borderRouter->GetEntry(index); + + aConfig.mExternalRoute = NULL; + aConfig.mService = NULL; + memset(aConfig.mOnMeshPrefix, 0, sizeof(OnMeshPrefixConfig)); + + memcpy(&aConfig.mOnMeshPrefix->mPrefix.mPrefix, prefix->GetPrefix(), + BitVectorBytes(prefix->GetPrefixLength())); + aConfig.mOnMeshPrefix->mPrefix.mLength = prefix->GetPrefixLength(); + aConfig.mOnMeshPrefix->mPreference = borderRouterEntry->GetPreference(); + aConfig.mOnMeshPrefix->mPreferred = borderRouterEntry->IsPreferred(); + aConfig.mOnMeshPrefix->mSlaac = borderRouterEntry->IsSlaac(); + aConfig.mOnMeshPrefix->mDhcp = borderRouterEntry->IsDhcp(); + aConfig.mOnMeshPrefix->mConfigure = borderRouterEntry->IsConfigure(); + aConfig.mOnMeshPrefix->mDefaultRoute = borderRouterEntry->IsDefaultRoute(); + aConfig.mOnMeshPrefix->mOnMesh = borderRouterEntry->IsOnMesh(); + aConfig.mOnMeshPrefix->mStable = borderRouter->IsStable(); + aConfig.mOnMeshPrefix->mRloc16 = borderRouterEntry->GetRloc(); + aConfig.mOnMeshPrefix->mNdDns = borderRouterEntry->IsNdDns(); + aConfig.mOnMeshPrefix->mDp = borderRouterEntry->IsDp(); + + ExitNow(error = OT_ERROR_NONE); + } + } + + break; + } + + case NetworkDataTlv::kTypeHasRoute: + { + const HasRouteTlv *hasRoute = static_cast(subCur); + + if (aConfig.mExternalRoute == NULL) + { + continue; + } + + for (uint8_t index; (index = iterator.GetAndAdvanceIndex()) < hasRoute->GetNumEntries();) + { + if (aRloc16 == Mac::kShortAddrBroadcast || hasRoute->GetEntry(index)->GetRloc() == aRloc16) + { + const HasRouteEntry *hasRouteEntry = hasRoute->GetEntry(index); + + aConfig.mOnMeshPrefix = NULL; + aConfig.mService = NULL; + memset(aConfig.mExternalRoute, 0, sizeof(ExternalRouteConfig)); + + memcpy(&aConfig.mExternalRoute->mPrefix.mPrefix, prefix->GetPrefix(), + BitVectorBytes(prefix->GetPrefixLength())); + aConfig.mExternalRoute->mPrefix.mLength = prefix->GetPrefixLength(); + aConfig.mExternalRoute->mPreference = hasRouteEntry->GetPreference(); + aConfig.mExternalRoute->mStable = hasRoute->IsStable(); + aConfig.mExternalRoute->mRloc16 = hasRouteEntry->GetRloc(); + aConfig.mExternalRoute->mNextHopIsThisDevice = + (hasRouteEntry->GetRloc() == Get().GetRloc16()); + + ExitNow(error = OT_ERROR_NONE); + } + } + + break; + } + + default: + break; + } + } + else // cur is `ServiceTLv` + { + const ServiceTlv *service = static_cast(cur); + + if (subCur->GetType() == NetworkDataTlv::kTypeServer) + { + const ServerTlv *server = static_cast(subCur); + + if (!iterator.IsNewEntry()) + { + continue; + } + + if ((aRloc16 == Mac::kShortAddrBroadcast) || (server->GetServer16() == aRloc16)) + { + aConfig.mOnMeshPrefix = NULL; + aConfig.mExternalRoute = NULL; + memset(aConfig.mService, 0, sizeof(ServiceConfig)); + + aConfig.mService->mServiceId = service->GetServiceId(); + aConfig.mService->mEnterpriseNumber = service->GetEnterpriseNumber(); + aConfig.mService->mServiceDataLength = service->GetServiceDataLength(); + + memcpy(&aConfig.mService->mServiceData, service->GetServiceData(), + service->GetServiceDataLength()); + + aConfig.mService->mServerConfig.mStable = server->IsStable(); + aConfig.mService->mServerConfig.mServerDataLength = server->GetServerDataLength(); + memcpy(&aConfig.mService->mServerConfig.mServerData, server->GetServerData(), + server->GetServerDataLength()); + aConfig.mService->mServerConfig.mRloc16 = server->GetServer16(); + + iterator.MarkEntryAsNotNew(); + + ExitNow(error = OT_ERROR_NONE); + } + } } } } @@ -804,59 +829,33 @@ exit: otError NetworkData::GetNextServer(Iterator &aIterator, uint16_t &aRloc16) const { - otError error = OT_ERROR_NONE; - NetworkDataIterator iterator(aIterator); + otError error; + OnMeshPrefixConfig prefixConfig; + ExternalRouteConfig routeConfig; + ServiceConfig serviceConfig; + Config config; - while (true) + config.mOnMeshPrefix = &prefixConfig; + config.mExternalRoute = &routeConfig; + config.mService = &serviceConfig; + + SuccessOrExit(error = Iterate(aIterator, Mac::kShortAddrBroadcast, config)); + + if (config.mOnMeshPrefix != NULL) { - switch (iterator.GetType()) - { - case NetworkDataIterator::kTypeOnMeshPrefix: - { - OnMeshPrefixConfig prefixConfig; - - if (GetNextOnMeshPrefix(aIterator, prefixConfig) == OT_ERROR_NONE) - { - aRloc16 = prefixConfig.mRloc16; - ExitNow(); - } - - iterator.SetType(NetworkDataIterator::kTypeExternalRoute); - break; - } - - case NetworkDataIterator::kTypeExternalRoute: - { - ExternalRouteConfig routeConfig; - - if (GetNextExternalRoute(aIterator, routeConfig) == OT_ERROR_NONE) - { - aRloc16 = routeConfig.mRloc16; - ExitNow(); - } - - iterator.SetType(NetworkDataIterator::kTypeService); - break; - } - - case NetworkDataIterator::kTypeService: - { - ServiceConfig serviceConfig; - - if (GetNextService(aIterator, serviceConfig) == OT_ERROR_NONE) - { - aRloc16 = serviceConfig.mServerConfig.mRloc16; - ExitNow(); - } - - ExitNow(error = OT_ERROR_NOT_FOUND); - } - } - - // Reset the iterator for next type. - iterator.SetTlvOffset(0); - iterator.SetSubTlvOffset(0); - iterator.SetEntryIndex(0); + aRloc16 = config.mOnMeshPrefix->mRloc16; + } + else if (config.mExternalRoute != NULL) + { + aRloc16 = config.mExternalRoute->mRloc16; + } + else if (config.mService != NULL) + { + aRloc16 = config.mService->mServerConfig.mRloc16; + } + else + { + OT_ASSERT(false); } exit: diff --git a/src/core/thread/network_data.hpp b/src/core/thread/network_data.hpp index ee39ed410..3b688f2c0 100644 --- a/src/core/thread/network_data.hpp +++ b/src/core/thread/network_data.hpp @@ -830,41 +830,55 @@ private: class NetworkDataIterator { public: - enum Type - { - kTypeOnMeshPrefix = 0, - kTypeExternalRoute = 1, - kTypeService = 2, - }; - explicit NetworkDataIterator(Iterator &aIterator) : mIteratorBuffer(reinterpret_cast(&aIterator)) { } - uint8_t GetTlvOffset(void) const { return mIteratorBuffer[kTlvPosition]; } - uint8_t GetSubTlvOffset(void) const { return mIteratorBuffer[kSubTlvPosition]; } - uint8_t GetEntryIndex(void) const { return mIteratorBuffer[kEntryPosition]; } - Type GetType(void) const { return static_cast(mIteratorBuffer[kTypePosition]); } - void SetTlvOffset(uint8_t aOffset) { mIteratorBuffer[kTlvPosition] = aOffset; } - void SetSubTlvOffset(uint8_t aOffset) { mIteratorBuffer[kSubTlvPosition] = aOffset; } - void SetEntryIndex(uint8_t aIndex) { mIteratorBuffer[kEntryPosition] = aIndex; } - void SetType(Type aType) { mIteratorBuffer[kTypePosition] = static_cast(aType); } - - bool IsNewEntry(void) const { return GetEntryIndex() == 0; } - void MarkEntryAsNotNew(void) { SetEntryIndex(1); } - const NetworkDataTlv *GetTlv(const uint8_t *aTlvs) const { return reinterpret_cast(aTlvs + GetTlvOffset()); } + void AdvanceTlv(const uint8_t *aTlvs) + { + SaveTlvOffset(GetTlv(aTlvs)->GetNext(), aTlvs); + SetSubTlvOffset(0); + SetEntryIndex(0); + } + const NetworkDataTlv *GetSubTlv(const NetworkDataTlv *aSubTlvs) const { return reinterpret_cast(reinterpret_cast(aSubTlvs) + GetSubTlvOffset()); } + void AdvaceSubTlv(const NetworkDataTlv *aSubTlvs) + { + SaveSubTlvOffset(GetSubTlv(aSubTlvs)->GetNext(), aSubTlvs); + SetEntryIndex(0); + } + + uint8_t GetAndAdvanceIndex(void) { return mIteratorBuffer[kEntryPosition]++; } + + bool IsNewEntry(void) const { return GetEntryIndex() == 0; } + void MarkEntryAsNotNew(void) { SetEntryIndex(1); } + + private: + enum + { + kTlvPosition = 0, + kSubTlvPosition = 1, + kEntryPosition = 2, + }; + + uint8_t GetTlvOffset(void) const { return mIteratorBuffer[kTlvPosition]; } + uint8_t GetSubTlvOffset(void) const { return mIteratorBuffer[kSubTlvPosition]; } + void SetSubTlvOffset(uint8_t aOffset) { mIteratorBuffer[kSubTlvPosition] = aOffset; } + void SetTlvOffset(uint8_t aOffset) { mIteratorBuffer[kTlvPosition] = aOffset; } + uint8_t GetEntryIndex(void) const { return mIteratorBuffer[kEntryPosition]; } + void SetEntryIndex(uint8_t aIndex) { mIteratorBuffer[kEntryPosition] = aIndex; } + void SaveTlvOffset(const NetworkDataTlv *aTlv, const uint8_t *aTlvs) { SetTlvOffset(static_cast(reinterpret_cast(aTlv) - aTlvs)); @@ -876,46 +890,24 @@ private: reinterpret_cast(aSubTlvs))); } - private: - enum - { - kTlvPosition = 0, - kSubTlvPosition = 1, - kEntryPosition = 2, - kTypePosition = 3, - }; - uint8_t *mIteratorBuffer; }; + struct Config + { + OnMeshPrefixConfig * mOnMeshPrefix; + ExternalRouteConfig *mExternalRoute; + ServiceConfig * mService; + }; + + otError Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aConfig) const; + static void RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength, PrefixTlv &aPrefix); static void RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength, ServiceTlv &aService); static void Remove(uint8_t *aData, uint8_t &aDataLength, uint8_t *aRemoveStart, uint8_t aRemoveLength); static void RemoveTlv(uint8_t *aData, uint8_t &aDataLength, NetworkDataTlv *aTlv); - const NetworkDataTlv *FindTlv(NetworkDataIterator &aIterator, NetworkDataTlv::Type aTlvType) const; - void IterateToNextTlv(NetworkDataIterator &aIterator) const; - const NetworkDataTlv *FindSubTlv(NetworkDataIterator & aIterator, - NetworkDataTlv::Type aSubTlvType, - const NetworkDataTlv *aSubTlvs, - const NetworkDataTlv *aSubTlvsEnd) const; - void IterateToNextSubTlv(NetworkDataIterator &aIterator, const NetworkDataTlv *aSubTlvs) const; - - template const TlvType *FindTlv(NetworkDataIterator &aIterator) const - { - return static_cast(FindTlv(aIterator, static_cast(TlvType::kType))); - } - - template - const TlvType *FindSubTlv(NetworkDataIterator & aIterator, - const NetworkDataTlv *aSubTlvs, - const NetworkDataTlv *aSubTlvsEnd) const - { - return static_cast( - FindSubTlv(aIterator, static_cast(TlvType::kType), aSubTlvs, aSubTlvsEnd)); - } - const Type mType; };