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,