From 50acd07a1712ec7f71f3b84a493b3b350c07403d Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Fri, 1 Jul 2016 10:47:40 -0700 Subject: [PATCH] Add API to retrieve router diag information. (#225) --- include/openthread-types.h | 18 +++++++++++ include/openthread.h | 9 ++++++ src/cli/README.md | 45 ++++++++++++++++++++++++++ src/cli/cli.cpp | 59 ++++++++++++++++++++++++++++++++++ src/cli/cli.hpp | 1 + src/core/openthread.cpp | 12 +++++++ src/core/thread/mle_router.cpp | 26 +++++++++++++++ src/core/thread/mle_router.hpp | 9 ++++++ 8 files changed, 179 insertions(+) diff --git a/include/openthread-types.h b/include/openthread-types.h index ab71d4ce3..f2bd481e1 100644 --- a/include/openthread-types.h +++ b/include/openthread-types.h @@ -394,6 +394,24 @@ typedef enum kDeviceRoleLeader, ///< The Thread Leader role. } otDeviceRole; +/** + * This structure holds diagnostics information for a Thread Router + * + */ +typedef struct +{ + otExtAddress mExtAddress; ///< IEEE 802.15.4 Extended Address + uint16_t mRloc16; ///< RLOC16 + uint8_t mRouterId; ///< Router ID + uint8_t mNextHop; ///< Next hop to router + uint8_t mPathCost; ///< Path cost to router + uint8_t mLinkQualityIn; ///< Link Quality In + uint8_t mLinkQualityOut; ///< Link Quality Out + uint8_t mAge; ///< Time last heard + bool mAllocated : 1; ///< Router ID allocated or not + bool mLinkEstablished : 1; ///< Link established with Router ID or not +} otRouterInfo; + /** * This structure represents the MAC layer counters. */ diff --git a/include/openthread.h b/include/openthread.h index ef78e6014..863d1b7f2 100644 --- a/include/openthread.h +++ b/include/openthread.h @@ -907,6 +907,15 @@ uint16_t otGetRloc16(void); */ uint8_t otGetRouterIdSequence(void); +/** + * The function retains diagnostic information for a given Thread Router. + * + * @param[in] aRouterId The router ID or RLOC16 for a given router. + * @param[out] aRouterInfo A pointer to where the router information is placed. + * + */ +ThreadError otGetRouterInfo(uint16_t aRouterId, otRouterInfo *aRouterInfo); + /** * Get the Stable Network Data Version. * diff --git a/src/cli/README.md b/src/cli/README.md index 890e8a5ad..a51a7e79d 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -27,6 +27,7 @@ OpenThread test scripts use the CLI to execute test cases. * [releaserouterid](#releaserouterid) * [rloc16](#rloc16) * [route](#route) +* [router](#router) * [routerupgradethreshold](#routerupgradethreshold) * [scan](#scan) * [start](#start) @@ -421,6 +422,50 @@ Invalidate a prefix in the Network Data. Done ``` +### router list + +List allocated Router IDs + +```bash +> router list +8 24 50 +Done +``` + +### router \ + +Print diagnostic information for a Thread Router. The `id` may be a Router ID or an RLOC16. + +```bash +> router 50 +Alloc: 1 +Router ID: 50 +Rloc: c800 +Next Hop: c800 +Link: 1 +Ext Addr: e2b3540590b0fd87 +Cost: 0 +LQI In: 3 +LQI Out: 3 +Age: 3 +Done +``` + +```bash +> router 0xc800 +Alloc: 1 +Router ID: 50 +Rloc: c800 +Next Hop: c800 +Link: 1 +Ext Addr: e2b3540590b0fd87 +Cost: 0 +LQI In: 3 +LQI Out: 3 +Age: 7 +Done +``` + ### routerupgradethreshold Get the ROUTER_UPGRADE_THRESHOLD value. diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index a25d70ed7..d96715d4a 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -70,6 +70,7 @@ const struct Command Interpreter::sCommands[] = { "releaserouterid", &ProcessReleaseRouterId }, { "rloc16", &ProcessRloc16 }, { "route", &ProcessRoute }, + { "router", &ProcessRouter }, { "routerupgradethreshold", &ProcessRouterUpgradeThreshold }, { "scan", &ProcessScan }, { "start", &ProcessStart }, @@ -923,6 +924,64 @@ exit: AppendResult(error); } +void Interpreter::ProcessRouter(int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + otRouterInfo routerInfo; + long value; + + VerifyOrExit(argc > 0, error = kThreadError_Parse); + + if (strcmp(argv[0], "list") == 0) + { + for (int i = 0; ; i++) + { + if (otGetRouterInfo(i, &routerInfo) != kThreadError_None) + { + sServer->OutputFormat("\r\n"); + ExitNow(); + } + + if (routerInfo.mAllocated) + { + sServer->OutputFormat("%d ", i); + } + } + } + + SuccessOrExit(error = ParseLong(argv[0], value)); + SuccessOrExit(error = otGetRouterInfo(value, &routerInfo)); + + sServer->OutputFormat("Alloc: %d\r\n", routerInfo.mAllocated); + + if (routerInfo.mAllocated) + { + sServer->OutputFormat("Router ID: %d\r\n", routerInfo.mRouterId); + sServer->OutputFormat("Rloc: %04x\r\n", routerInfo.mRloc16); + sServer->OutputFormat("Next Hop: %04x\r\n", static_cast(routerInfo.mNextHop) << 10); + sServer->OutputFormat("Link: %d\r\n", routerInfo.mLinkEstablished); + + if (routerInfo.mLinkEstablished) + { + sServer->OutputFormat("Ext Addr: "); + + for (int j = 0; j < sizeof(routerInfo.mExtAddress); j++) + { + sServer->OutputFormat("%02x", routerInfo.mExtAddress.m8[j]); + } + + sServer->OutputFormat("\r\n"); + sServer->OutputFormat("Cost: %d\r\n", routerInfo.mPathCost); + sServer->OutputFormat("LQI In: %d\r\n", routerInfo.mLinkQualityIn); + sServer->OutputFormat("LQI Out: %d\r\n", routerInfo.mLinkQualityOut); + sServer->OutputFormat("Age: %d\r\n", routerInfo.mAge); + } + } + +exit: + AppendResult(error); +} + void Interpreter::ProcessRouterUpgradeThreshold(int argc, char *argv[]) { ThreadError error = kThreadError_None; diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index a6afc297e..825073ab8 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -110,6 +110,7 @@ private: static ThreadError ProcessPrefixRemove(int argc, char *argv[]); static void ProcessReleaseRouterId(int argc, char *argv[]); static void ProcessRoute(int argc, char *argv[]); + static void ProcessRouter(int argc, char *argv[]); static ThreadError ProcessRouteAdd(int argc, char *argv[]); static ThreadError ProcessRouteRemove(int argc, char *argv[]); static void ProcessRouterUpgradeThreshold(int argc, char *argv[]); diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index 05ba554df..678b3182d 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -514,6 +514,18 @@ uint8_t otGetRouterIdSequence(void) return sThreadNetif->GetMle().GetRouterIdSequence(); } +ThreadError otGetRouterInfo(uint16_t aRouterId, otRouterInfo *aRouterInfo) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aRouterInfo != NULL, error = kThreadError_InvalidArgs); + + error = sThreadNetif->GetMle().GetRouterInfo(aRouterId, *aRouterInfo); + +exit: + return error; +} + uint8_t otGetStableNetworkDataVersion(void) { return sThreadNetif->GetMle().GetLeaderDataTlv().GetStableDataVersion(); diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index c953260d5..52f304989 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -2252,6 +2252,32 @@ Router *MleRouter::GetRouters(uint8_t *aNumRouters) return mRouters; } +ThreadError MleRouter::GetRouterInfo(uint16_t aRouterId, otRouterInfo &aRouterInfo) +{ + ThreadError error = kThreadError_None; + + if (aRouterId > kMaxRouterId && GetChildId(aRouterId) == 0) + { + aRouterId = GetRouterId(aRouterId); + } + + VerifyOrExit(aRouterId <= kMaxRouterId, error = kThreadError_InvalidArgs); + + memcpy(&aRouterInfo.mExtAddress, &mRouters[aRouterId].mMacAddr, sizeof(aRouterInfo.mExtAddress)); + aRouterInfo.mAllocated = mRouters[aRouterId].mAllocated; + aRouterInfo.mRouterId = aRouterId; + aRouterInfo.mRloc16 = GetRloc16(aRouterId); + aRouterInfo.mNextHop = mRouters[aRouterId].mNextHop; + aRouterInfo.mLinkEstablished = mRouters[aRouterId].mState == Neighbor::kStateValid; + aRouterInfo.mPathCost = mRouters[aRouterId].mCost; + aRouterInfo.mLinkQualityIn = mRouters[aRouterId].mLinkInfo.GetLinkQuality(); + aRouterInfo.mLinkQualityOut = mRouters[aRouterId].mLinkQualityOut; + aRouterInfo.mAge = Timer::MsecToSec(Timer::GetNow() - mRouters[aRouterId].mLastHeard); + +exit: + return error; +} + ThreadError MleRouter::CheckReachability(uint16_t aMeshSource, uint16_t aMeshDest, Ip6::Header &aIp6Header) { Ip6::Address destination; diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index 988fb4cb0..dba9c269d 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -289,6 +289,15 @@ public: */ Router *GetRouters(uint8_t *aNumRouters); + /** + * This method retains diagnotsic information for a given router. + * + * @param[in] aRouterId The router ID or RLOC16 for a given router. + * @param[out] aRouterInfo The router information. + * + */ + ThreadError GetRouterInfo(uint16_t aRouterId, otRouterInfo &aRouterInfo); + /** * This method handles MAC Data Poll messages. *