From 55074652907295709f9f3361244a6e76f732bcba Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 8 Feb 2023 15:07:19 -0800 Subject: [PATCH] [cli] `nexthop` command to output next hop and path cost table (#8729) This commit extends `nexthop` command such that when it is used without any input, it lists all currently allocated router IDs and the next hop and path cost for each. Note that this info is different from `router table` (which provides direct link along with any backup next hop option). This commit also adds a new API `otThreadIsRouterIdAllocated()` to indicate whether or not a given router ID is currently allocated. --- include/openthread/instance.h | 2 +- include/openthread/thread_ftd.h | 12 ++++ src/cli/cli.cpp | 102 ++++++++++++++++++++++++++------ src/core/api/thread_ftd_api.cpp | 5 ++ 4 files changed, 103 insertions(+), 18 deletions(-) diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 70d50235b..2d39be70d 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (282) +#define OPENTHREAD_API_VERSION (283) /** * @addtogroup api-instance diff --git a/include/openthread/thread_ftd.h b/include/openthread/thread_ftd.h index ca89335aa..994ab4851 100644 --- a/include/openthread/thread_ftd.h +++ b/include/openthread/thread_ftd.h @@ -817,6 +817,18 @@ void otThreadGetRouterIdRange(otInstance *aInstance, uint8_t *aMinRouterId, uint */ otError otThreadSetRouterIdRange(otInstance *aInstance, uint8_t aMinRouterId, uint8_t aMaxRouterId); +/** + * This function indicates whether or not a Router ID is currently allocated. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aRouterId The router ID to check. + * + * @retval TRUE The @p aRouterId is allocated. + * @retval FALSE The @p aRouterId is not allocated. + * + */ +bool otThreadIsRouterIdAllocated(otInstance *aInstance, uint8_t aRouterId); + /** * This function gets the next hop and path cost towards a given RLOC16 destination. * diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 9d94811b4..e78b61b2d 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -5465,30 +5465,98 @@ exit: #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE #if OPENTHREAD_FTD -/** - * @cli nexthop - * @code - * nexthop 0xc000 - * 0xc000 cost:0 - * Done - * nexthop 0x8001 - * 0x2000 cost:3 - * Done - * @endcode - * @cparam nexthop @ca{rloc16} - * @par api_copy - * #otThreadGetNextHopAndPathCost - */ template <> otError Interpreter::Process(Arg aArgs[]) { + constexpr uint8_t kRouterIdOffset = 10; // Bit offset of Router ID in RLOC16 + constexpr uint16_t kInvalidRloc16 = 0xfffe; + otError error = OT_ERROR_NONE; uint16_t destRloc16; uint16_t nextHopRloc16; uint8_t pathCost; - SuccessOrExit(error = aArgs[0].ParseAsUint16(destRloc16)); - otThreadGetNextHopAndPathCost(GetInstancePtr(), destRloc16, &nextHopRloc16, &pathCost); - OutputLine("0x%04x cost:%u", nextHopRloc16, pathCost); + /** + * @cli nexthop + * @code + * nexthop + * | ID |NxtHop| Cost | + * +------+------+------+ + * | 9 | 9 | 1 | + * | 25 | 25 | 0 | + * | 30 | 30 | 1 | + * | 46 | - | - | + * | 50 | 30 | 3 | + * | 60 | 30 | 2 | + * Done + * @endcode + * @par + * Output table of allocated Router IDs and current next hop and path + * cost for each router. + * @sa otThreadGetNextHopAndPathCost + * @sa otThreadIsRouterIdAllocated + */ + if (aArgs[0].IsEmpty()) + { + static const char *const kNextHopTableTitles[] = { + "ID", + "NxtHop", + "Cost", + }; + + static const uint8_t kNextHopTableColumnWidths[] = { + 6, + 6, + 6, + }; + + OutputTableHeader(kNextHopTableTitles, kNextHopTableColumnWidths); + + for (uint8_t routerId = 0; routerId <= OT_NETWORK_MAX_ROUTER_ID; routerId++) + { + if (!otThreadIsRouterIdAllocated(GetInstancePtr(), routerId)) + { + continue; + } + + destRloc16 = routerId; + destRloc16 <<= kRouterIdOffset; + + otThreadGetNextHopAndPathCost(GetInstancePtr(), destRloc16, &nextHopRloc16, &pathCost); + + OutputFormat("| %4u | ", routerId); + + if (nextHopRloc16 != kInvalidRloc16) + { + OutputLine("%4u | %4u |", nextHopRloc16 >> kRouterIdOffset, pathCost); + } + else + { + OutputLine("%4s | %4s |", "-", "-"); + } + } + } + /** + * @cli nexthop (get) + * @code + * nexthop 0xc000 + * 0xc000 cost:0 + * Done + * @endcode + * @code + * nexthop 0x8001 + * 0x2000 cost:3 + * Done + * @endcode + * @cparam nexthop @ca{rloc16} + * @par api_copy + * #otThreadGetNextHopAndPathCost + */ + else + { + SuccessOrExit(error = aArgs[0].ParseAsUint16(destRloc16)); + otThreadGetNextHopAndPathCost(GetInstancePtr(), destRloc16, &nextHopRloc16, &pathCost); + OutputLine("0x%04x cost:%u", nextHopRloc16, pathCost); + } exit: return error; diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp index 166c83104..2c90cb08e 100644 --- a/src/core/api/thread_ftd_api.cpp +++ b/src/core/api/thread_ftd_api.cpp @@ -391,6 +391,11 @@ otError otThreadSetRouterIdRange(otInstance *aInstance, uint8_t aMinRouterId, ui } #endif +bool otThreadIsRouterIdAllocated(otInstance *aInstance, uint8_t aRouterId) +{ + return AsCoreType(aInstance).Get().IsAllocated(aRouterId); +} + void otThreadGetNextHopAndPathCost(otInstance *aInstance, uint16_t aDestRloc16, uint16_t *aNextHopRloc16,