From 5755f99cae8e6a34bec3f28177061c8a544fbf71 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Tue, 16 Aug 2016 19:10:41 -0700 Subject: [PATCH] Provide an API to retrieve the list of on-mesh prefixes. (#392) --- include/openthread-types.h | 4 ++ include/openthread.h | 13 ++++++ src/cli/cli.cpp | 76 ++++++++++++++++++++++++++++++-- src/cli/cli.hpp | 1 + src/core/openthread.cpp | 19 ++++++++ src/core/thread/network_data.cpp | 46 +++++++++++++++++++ src/core/thread/network_data.hpp | 12 +++++ 7 files changed, 168 insertions(+), 3 deletions(-) diff --git a/include/openthread-types.h b/include/openthread-types.h index c8567f797..bdcda7aa7 100644 --- a/include/openthread-types.h +++ b/include/openthread-types.h @@ -380,6 +380,10 @@ typedef struct otIp6Prefix uint8_t mLength; ///< The IPv6 prefix length. } otIp6Prefix; +#define OT_NETWORK_DATA_ITERATOR_INIT 0 ///< Initializeer for otNetworkDataIterator. + +typedef uint8_t otNetworkDataIterator; ///< Used to iterate through Network Data information. + /** * This structure represents a Border Router configuration. */ diff --git a/include/openthread.h b/include/openthread.h index dfe5c6e6e..55b3c476a 100644 --- a/include/openthread.h +++ b/include/openthread.h @@ -498,6 +498,19 @@ const char *otGetNetworkName(void); */ ThreadError otSetNetworkName(const char *aNetworkName); +/** + * This function gets the next On Mesh Prefix in the Network Data. + * + * @param[in] aLocal TRUE to retrieve from the local Network Data, FALSE for partition's Network Data + * @param[inout] aIterator A pointer to the Network Data iterator context. + * @param[out] aConfig A pointer to where the On Mesh Prefix information will be placed. + * + * @retval kThreadError_None Successfully found the next On Mesh prefix. + * @retval kThreadError_NotFound No subsequent On Mesh prefix exists in the Thread Network Data. + * + */ +ThreadError otGetNextOnMeshPrefix(bool aLocal, otNetworkDataIterator *aIterator, otBorderRouterConfig *aConfig); + /** * Get the IEEE 802.15.4 PAN ID. * diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index cca3cb1a8..6c4c419fa 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -1176,13 +1176,83 @@ exit: return error; } +ThreadError Interpreter::ProcessPrefixList(void) +{ + otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT; + otBorderRouterConfig config; + + while (otGetNextOnMeshPrefix(true, &iterator, &config) == kThreadError_None) + { + sServer->OutputFormat("%x:%x:%x:%x::/%d ", + HostSwap16(config.mPrefix.mPrefix.mFields.m16[0]), + HostSwap16(config.mPrefix.mPrefix.mFields.m16[1]), + HostSwap16(config.mPrefix.mPrefix.mFields.m16[2]), + HostSwap16(config.mPrefix.mPrefix.mFields.m16[3]), + config.mPrefix.mLength); + + if (config.mPreferred) + { + sServer->OutputFormat("p"); + } + + if (config.mSlaac) + { + sServer->OutputFormat("a"); + } + + if (config.mDhcp) + { + sServer->OutputFormat("d"); + } + + if (config.mConfigure) + { + sServer->OutputFormat("c"); + } + + if (config.mDefaultRoute) + { + sServer->OutputFormat("r"); + } + + if (config.mOnMesh) + { + sServer->OutputFormat("o"); + } + + if (config.mStable) + { + sServer->OutputFormat("s"); + } + + switch (config.mPreference) + { + case -1: + sServer->OutputFormat(" low\r\n"); + break; + + case 0: + sServer->OutputFormat(" med\r\n"); + break; + + case 1: + sServer->OutputFormat(" high\r\n"); + break; + } + } + + return kThreadError_None; +} + void Interpreter::ProcessPrefix(int argc, char *argv[]) { ThreadError error = kThreadError_None; - VerifyOrExit(argc > 0, error = kThreadError_Parse); - - if (strcmp(argv[0], "add") == 0) + if (argc == 0) + { + SuccessOrExit(error = ProcessPrefixList()); + } + else if (strcmp(argv[0], "add") == 0) { SuccessOrExit(error = ProcessPrefixAdd(argc - 1, argv + 1)); } diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index ea76b7720..e2a760bba 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -162,6 +162,7 @@ private: static void ProcessPrefix(int argc, char *argv[]); static ThreadError ProcessPrefixAdd(int argc, char *argv[]); static ThreadError ProcessPrefixRemove(int argc, char *argv[]); + static ThreadError ProcessPrefixList(void); static void ProcessReleaseRouterId(int argc, char *argv[]); static void ProcessReset(int argc, char *argv[]); static void ProcessRoute(int argc, char *argv[]); diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index 5d81e95f0..6ab8b6513 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -348,6 +348,25 @@ ThreadError otRemoveBorderRouter(const otIp6Prefix *aPrefix) return sThreadNetif->GetNetworkDataLocal().RemoveOnMeshPrefix(aPrefix->mPrefix.mFields.m8, aPrefix->mLength); } +ThreadError otGetNextOnMeshPrefix(bool aLocal, otNetworkDataIterator *aIterator, otBorderRouterConfig *aConfig) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aIterator && aConfig, error = kThreadError_InvalidArgs); + + if (aLocal) + { + error = sThreadNetif->GetNetworkDataLocal().GetNextOnMeshPrefix(aIterator, aConfig); + } + else + { + error = sThreadNetif->GetNetworkDataLeader().GetNextOnMeshPrefix(aIterator, aConfig); + } + +exit: + return error; +} + ThreadError otAddExternalRoute(const otExternalRouteConfig *aConfig) { return sThreadNetif->GetNetworkDataLocal().AddHasRoutePrefix(aConfig->mPrefix.mPrefix.mFields.m8, diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp index 4bb3aceeb..f981f215c 100644 --- a/src/core/thread/network_data.cpp +++ b/src/core/thread/network_data.cpp @@ -57,6 +57,52 @@ void NetworkData::GetNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLen } } +ThreadError NetworkData::GetNextOnMeshPrefix(otNetworkDataIterator *aIterator, otBorderRouterConfig *aConfig) +{ + ThreadError error = kThreadError_NotFound; + NetworkDataTlv *cur = reinterpret_cast(mTlvs + *aIterator); + NetworkDataTlv *end = reinterpret_cast(mTlvs + mLength); + + for (; cur < end; cur = cur->GetNext()) + { + PrefixTlv *prefix; + BorderRouterTlv *borderRouter; + BorderRouterEntry *borderRouterEntry; + + if (cur->GetType() != NetworkDataTlv::kTypePrefix) + { + continue; + } + + prefix = static_cast(cur); + + if ((borderRouter = FindBorderRouter(*prefix)) == NULL) + { + continue; + } + + borderRouterEntry = borderRouter->GetEntry(0); + + memcpy(&aConfig->mPrefix.mPrefix, prefix->GetPrefix(), sizeof(aConfig->mPrefix.mPrefix)); + 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 = cur->IsStable(); + + *aIterator = static_cast(reinterpret_cast(cur->GetNext()) - mTlvs); + + ExitNow(error = kThreadError_None); + } + +exit: + return error; +} + void NetworkData::RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength) { NetworkDataTlv *cur = reinterpret_cast(aData); diff --git a/src/core/thread/network_data.hpp b/src/core/thread/network_data.hpp index 91063575c..6514c5d26 100644 --- a/src/core/thread/network_data.hpp +++ b/src/core/thread/network_data.hpp @@ -103,6 +103,18 @@ public: */ void GetNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLength); + /** + * This method provides the next On Mesh prefix in the Thread Network Data. + * + * @param[out] aIterator A pointer to the Network Data iterator context. + * @param[out] aConfig A pointer to where the On Mesh Prefix information will be placed. + * + * @retval kThreadError_None Successfully found the next On Mesh prefix. + * @retval kThreadError_NotFound No subsequent On Mesh prefix exists in the Thread Network Data. + * + */ + ThreadError GetNextOnMeshPrefix(otNetworkDataIterator *aIterator, otBorderRouterConfig *aConfig); + protected: /** * This method returns a pointer to the Border Router TLV within a given Prefix TLV.