diff --git a/include/openthread/thread_ftd.h b/include/openthread/thread_ftd.h index c27a9483c..d9db8624e 100644 --- a/include/openthread/thread_ftd.h +++ b/include/openthread/thread_ftd.h @@ -78,17 +78,46 @@ typedef struct typedef uint16_t otChildIp6AddressIterator; ///< Used to iterate through IPv6 addresses of a Thread Child entry. +/** + * This enumeration defines the EID cache entry state. + * + */ +typedef enum otCacheEntryState +{ + OT_CACHE_ENTRY_STATE_CACHED = 0, // Entry is cached and in-use. + OT_CACHE_ENTRY_STATE_SNOOPED = 1, // Entry is created by snoop optimization (inspection of received msg). + OT_CACHE_ENTRY_STATE_QUERY = 2, // Entry represents an ongoing query for the EID. + OT_CACHE_ENTRY_STATE_RETRY_QUERY = 3, // Entry is in retry wait mode (a prior query did not get a response). +} otCacheEntryState; + /** * This structure represents an EID cache entry. * */ -typedef struct otEidCacheEntry +typedef struct otCacheEntryInfo { - otIp6Address mTarget; ///< Target - otShortAddress mRloc16; ///< RLOC16 - uint8_t mAge; ///< Age (order of use, 0 indicates most recently used entry) - bool mValid : 1; ///< Indicates whether or not the cache entry is valid -} otEidCacheEntry; + otIp6Address mTarget; ///< Target EID + otShortAddress mRloc16; ///< RLOC16 + otCacheEntryState mState; ///< Entry state + bool mCanEvict : 1; ///< Indicates whether the entry can be evicted. + bool mValidLastTrans : 1; ///< Indicates whether last transaction time and ML-EID are valid. + uint32_t mLastTransTime; ///< Last transaction time (applicable in cached state). + otIp6Address mMeshLocalEid; ///< Mesh Local EID (applicable if entry in cached state). + uint16_t mTimeout; ///< Timeout in seconds (applicable if in snooped/query/retry-query states). + uint16_t mRetryDelay; ///< Retry delay in seconds (applicable if in query-retry state). +} otCacheEntryInfo; + +/** + * This type represents an iterator used for iterating through the EID cache table entries. + * + * To initialize the iterator and start from the first entry in the cache table, set all its fields in the structure to + * zero (e.g., `memset` the iterator to zero). + * + */ +typedef struct otCacheEntryIterator +{ + const void *mData[2]; ///< Opaque data used by the core implementation. Should not be changed by user. +} otCacheEntryIterator; /** * Get the maximum number of children currently allowed. @@ -507,17 +536,19 @@ uint8_t otThreadGetMaxRouterId(otInstance *aInstance); otError otThreadGetRouterInfo(otInstance *aInstance, uint16_t aRouterId, otRouterInfo *aRouterInfo); /** - * This function gets an EID cache entry. + * This function gets the next EID cache entry (using an iterator). * - * @param[in] aInstance A pointer to an OpenThread instance. - * @param[in] aIndex An index into the EID cache table. - * @param[out] aEntry A pointer to where the EID information is placed. + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[out] aEntryInfo A pointer to where the EID cache entry information is placed. + * @param[inout] aIterator A pointer to an iterator. It will be updated to point to next entry on success. To get the + * first entry, initialize the iterator by setting all its fields to zero (e.g., `memset` the + * the iterator structure to zero). * - * @retval OT_ERROR_NONE Successfully retrieved the EID cache entry. - * @retval OT_ERROR_INVALID_ARGS @p aIndex was out of bounds or @p aEntry was NULL. + * @retval OT_ERROR_NONE Successfully populated @p aEntryInfo for next EID cache entry. + * @retval OT_ERROR_NOT_FOUND No more entries in the address cache table. * */ -otError otThreadGetEidCacheEntry(otInstance *aInstance, uint8_t aIndex, otEidCacheEntry *aEntry); +otError otThreadGetNextCacheEntry(otInstance *aInstance, otCacheEntryInfo *aEntryInfo, otCacheEntryIterator *aIterator); /** * Get the Thread PSKc diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index e3746a33c..bfe4b3ced 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -1294,16 +1294,14 @@ void Interpreter::ProcessEidCache(uint8_t aArgsLength, char *aArgs[]) OT_UNUSED_VARIABLE(aArgsLength); OT_UNUSED_VARIABLE(aArgs); - otEidCacheEntry entry; + otCacheEntryIterator iterator; + otCacheEntryInfo entry; + + memset(&iterator, 0, sizeof(iterator)); for (uint8_t i = 0;; i++) { - SuccessOrExit(otThreadGetEidCacheEntry(mInstance, i, &entry)); - - if (!entry.mValid) - { - continue; - } + SuccessOrExit(otThreadGetNextCacheEntry(mInstance, &entry, &iterator)); OutputIp6Address(entry.mTarget); mServer->OutputFormat(" %04x\r\n", entry.mRloc16); diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp index c102e84f3..cc564dedd 100644 --- a/src/core/api/thread_ftd_api.cpp +++ b/src/core/api/thread_ftd_api.cpp @@ -316,12 +316,13 @@ otError otThreadGetRouterInfo(otInstance *aInstance, uint16_t aRouterId, otRoute return instance.Get().GetRouterInfo(aRouterId, *aRouterInfo); } -otError otThreadGetEidCacheEntry(otInstance *aInstance, uint8_t aIndex, otEidCacheEntry *aEntry) +otError otThreadGetNextCacheEntry(otInstance *aInstance, otCacheEntryInfo *aEntryInfo, otCacheEntryIterator *aIterator) { Instance &instance = *static_cast(aInstance); - OT_ASSERT(aEntry != NULL); - return instance.Get().GetEntry(aIndex, *aEntry); + OT_ASSERT((aIterator != NULL) && (aEntryInfo != NULL)); + + return instance.Get().GetNextCacheEntry(*aEntryInfo, *aIterator); } #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE diff --git a/src/core/thread/address_resolver.cpp b/src/core/thread/address_resolver.cpp index f50a12807..23876d1d2 100644 --- a/src/core/thread/address_resolver.cpp +++ b/src/core/thread/address_resolver.cpp @@ -99,30 +99,81 @@ void AddressResolver::Clear(void) } } -otError AddressResolver::GetEntry(uint8_t aIndex, otEidCacheEntry &aEntry) const +otError AddressResolver::GetNextCacheEntry(EntryInfo &aInfo, Iterator &aIterator) const { - otError error = OT_ERROR_NONE; - uint8_t age = aIndex; - const CacheEntryList *lists[] = {&mCachedList, &mSnoopedList}; + otError error = OT_ERROR_NONE; + const CacheEntryList *list; const CacheEntry * entry; - for (uint8_t index = 0; index < OT_ARRAY_LENGTH(lists); index++) - { - for (entry = lists[index]->GetHead(); (aIndex != 0) && (entry != NULL); aIndex--, entry = entry->GetNext()) - ; + list = reinterpret_cast(aIterator.mData[kIteratorListIndex]); + entry = reinterpret_cast(aIterator.mData[kIteratorEntryIndex]); - if (entry != NULL) + while (entry == NULL) + { + if (list == NULL) { - break; + list = &mCachedList; } + else if (list == &mCachedList) + { + list = &mSnoopedList; + } + else if (list == &mSnoopedList) + { + list = &mQueryList; + } + else if (list == &mQueryList) + { + list = &mQueryRetryList; + } + else + { + ExitNow(error = OT_ERROR_NOT_FOUND); + } + + entry = list->GetHead(); } - VerifyOrExit(entry != NULL, error = OT_ERROR_NOT_FOUND); + // Update the iterator then populate the `aInfo`. - aEntry.mTarget = entry->GetTarget(); - aEntry.mRloc16 = entry->GetRloc16(); - aEntry.mAge = age; - aEntry.mValid = true; + aIterator.mData[kIteratorEntryIndex] = entry->GetNext(); + aIterator.mData[kIteratorListIndex] = list; + + memset(&aInfo, 0, sizeof(aInfo)); + aInfo.mTarget = entry->GetTarget(); + aInfo.mRloc16 = entry->GetRloc16(); + + if (list == &mCachedList) + { + aInfo.mState = OT_CACHE_ENTRY_STATE_CACHED; + aInfo.mCanEvict = true; + aInfo.mValidLastTrans = entry->IsLastTransactionTimeValid(); + + VerifyOrExit(entry->IsLastTransactionTimeValid()); + + aInfo.mLastTransTime = entry->GetLastTransactionTime(); + static_cast(aInfo.mMeshLocalEid).SetPrefix(Get().GetMeshLocalPrefix()); + static_cast(aInfo.mMeshLocalEid).SetIid(entry->GetMeshLocalIid()); + + ExitNow(); + } + + if (list == &mSnoopedList) + { + aInfo.mState = OT_CACHE_ENTRY_STATE_SNOOPED; + } + else if (list == &mQueryList) + { + aInfo.mState = OT_CACHE_ENTRY_STATE_QUERY; + } + else + { + aInfo.mState = OT_CACHE_ENTRY_STATE_RETRY_QUERY; + } + + aInfo.mCanEvict = entry->CanEvict(); + aInfo.mTimeout = entry->GetTimeout(); + aInfo.mRetryDelay = entry->GetRetryDelay(); exit: return error; diff --git a/src/core/thread/address_resolver.hpp b/src/core/thread/address_resolver.hpp index eba518359..759fc7045 100644 --- a/src/core/thread/address_resolver.hpp +++ b/src/core/thread/address_resolver.hpp @@ -63,6 +63,18 @@ namespace ot { class AddressResolver : public InstanceLocator { public: + /** + * This type represents an iterator used for iterating through the EID cache table entries. + * + */ + typedef otCacheEntryIterator Iterator; + + /** + * This type represents an EID cache entry. + * + */ + typedef otCacheEntryInfo EntryInfo; + /** * This constructor initializes the object. * @@ -76,16 +88,18 @@ public: void Clear(void); /** - * This method gets an EID cache entry. + * This method gets the information about the next EID cache entry (using an iterator). * - * @param[in] aIndex An index into the EID cache table. - * @param[out] aEntry A reference to where the EID information is placed. + * @param[out] aInfo An `EntryInfo` where the EID cache entry information is placed. + * @param[inout] aIterator An iterator. It will be updated to point to the next entry on success. + * To get the first entry, initialize the iterator by setting all its fields to zero. + * e.g., `memset` the the iterator structure to zero. * - * @retval OT_ERROR_NONE Successfully retrieved the EID cache entry. - * @retval OT_ERROR_INVALID_ARGS @p aIndex was out of bounds. + * @retval OT_ERROR_NONE Successfully populated @p aInfo with the info for the next EID cache entry. + * @retval OT_ERROR_NOT_FOUND No more entries in the address cache table. * */ - otError GetEntry(uint8_t aIndex, otEidCacheEntry &aEntry) const; + otError GetNextCacheEntry(EntryInfo &aInfo, Iterator &aIterator) const; /** * This method removes the EID-to-RLOC cache entries corresponding to an RLOC16. @@ -170,6 +184,8 @@ private: kAddressQueryMaxRetryDelay = OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_MAX_RETRY_DELAY, // in seconds kSnoopBlockEvictionTimeout = OPENTHREAD_CONFIG_TMF_SNOOP_CACHE_ENTRY_TIMEOUT, // in seconds kStateUpdatePeriod = 1000u, // in milliseconds + kIteratorListIndex = 0, + kIteratorEntryIndex = 1, }; class CacheEntry : public InstanceLocatorInit diff --git a/src/ncp/ncp_base_ftd.cpp b/src/ncp/ncp_base_ftd.cpp index dde5c9d0e..3422684b0 100644 --- a/src/ncp/ncp_base_ftd.cpp +++ b/src/ncp/ncp_base_ftd.cpp @@ -911,22 +911,20 @@ exit: template <> otError NcpBase::HandlePropertyGet(void) { - otError error = OT_ERROR_NONE; - otEidCacheEntry entry; + otError error = OT_ERROR_NONE; + otCacheEntryIterator iterator; + otCacheEntryInfo entry; + + memset(&iterator, 0, sizeof(iterator)); for (uint8_t index = 0;; index++) { - SuccessOrExit(otThreadGetEidCacheEntry(mInstance, index, &entry)); - - if (!entry.mValid) - { - continue; - } + SuccessOrExit(otThreadGetNextCacheEntry(mInstance, &entry, &iterator)); SuccessOrExit(error = mEncoder.OpenStruct()); SuccessOrExit(error = mEncoder.WriteIp6Address(entry.mTarget)); SuccessOrExit(error = mEncoder.WriteUint16(entry.mRloc16)); - SuccessOrExit(error = mEncoder.WriteUint8(entry.mAge)); + SuccessOrExit(error = mEncoder.WriteUint8(index)); SuccessOrExit(error = mEncoder.CloseStruct()); }