1 /* 2 * Copyright (c) 2023, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * @brief 32 * This file defines the OpenThread Mesh Diagnostic APIs. 33 */ 34 35 #ifndef OPENTHREAD_MESH_DIAG_H_ 36 #define OPENTHREAD_MESH_DIAG_H_ 37 38 #include <openthread/instance.h> 39 #include <openthread/thread.h> 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 /** 46 * @addtogroup api-mesh-diag 47 * 48 * @brief 49 * This module includes definitions and functions for Mesh Diagnostics. 50 * 51 * The Mesh Diagnostics APIs require `OPENTHREAD_CONFIG_MESH_DIAG_ENABLE` and `OPENTHREAD_FTD`. 52 * 53 * @{ 54 */ 55 56 /** 57 * Represents the set of configurations used when discovering mesh topology indicating which items to 58 * discover. 59 */ 60 typedef struct otMeshDiagDiscoverConfig 61 { 62 bool mDiscoverIp6Addresses : 1; ///< Whether or not to discover IPv6 addresses of every router. 63 bool mDiscoverChildTable : 1; ///< Whether or not to discover children of every router. 64 } otMeshDiagDiscoverConfig; 65 66 /** 67 * An opaque iterator to iterate over list of IPv6 addresses of a router. 68 * 69 * Pointers to instance of this type are provided in `otMeshDiagRouterInfo`. 70 */ 71 typedef struct otMeshDiagIp6AddrIterator otMeshDiagIp6AddrIterator; 72 73 /** 74 * An opaque iterator to iterate over list of children of a router. 75 * 76 * Pointers to instance of this type are provided in `otMeshDiagRouterInfo`. 77 */ 78 typedef struct otMeshDiagChildIterator otMeshDiagChildIterator; 79 80 /** 81 * Specifies that Thread Version is unknown. 82 * 83 * This is used in `otMeshDiagRouterInfo` for `mVersion` property when device does not provide its version. This 84 * indicates that device is likely running 1.3.0 (version value 4) or earlier. 85 */ 86 #define OT_MESH_DIAG_VERSION_UNKNOWN 0xffff 87 88 /** 89 * Represents information about a router in Thread mesh discovered using `otMeshDiagDiscoverTopology()`. 90 */ 91 typedef struct otMeshDiagRouterInfo 92 { 93 otExtAddress mExtAddress; ///< Extended MAC address. 94 uint16_t mRloc16; ///< RLOC16. 95 uint8_t mRouterId; ///< Router ID. 96 uint16_t mVersion; ///< Thread Version. `OT_MESH_DIAG_VERSION_UNKNOWN` if unknown. 97 bool mIsThisDevice : 1; ///< Whether router is this device itself. 98 bool mIsThisDeviceParent : 1; ///< Whether router is parent of this device (when device is a child). 99 bool mIsLeader : 1; ///< Whether router is leader. 100 bool mIsBorderRouter : 1; ///< Whether router acts as a border router providing ext connectivity. 101 102 /** 103 * Provides the link quality from this router to other routers, also indicating whether a link is established 104 * between the routers. 105 * 106 * The array is indexed based on Router ID. `mLinkQualities[routerId]` indicates the incoming link quality, the 107 * router sees to the router with `routerId`. Link quality is a value in [0, 3]. Value zero indicates no link. 108 * Larger value indicate better link quality (as defined by Thread specification). 109 */ 110 uint8_t mLinkQualities[OT_NETWORK_MAX_ROUTER_ID + 1]; 111 112 /** 113 * A pointer to an iterator to go through the list of IPv6 addresses of the router. 114 * 115 * The pointer is valid only while `otMeshDiagRouterInfo` is valid. It can be used in `otMeshDiagGetNextIp6Address` 116 * to iterate through the IPv6 addresses. 117 * 118 * The pointer can be NULL when there was no request to discover IPv6 addresses (in `otMeshDiagDiscoverConfig`) or 119 * if the router did not provide the list. 120 */ 121 otMeshDiagIp6AddrIterator *mIp6AddrIterator; 122 123 /** 124 * A pointer to an iterator to go through the list of children of the router. 125 * 126 * The pointer is valid only while `otMeshDiagRouterInfo` is valid. It can be used in `otMeshDiagGetNextChildInfo` 127 * to iterate through the children of the router. 128 * 129 * The pointer can be NULL when there was no request to discover children (in `otMeshDiagDiscoverConfig`) or 130 * if the router did not provide the list. 131 */ 132 otMeshDiagChildIterator *mChildIterator; 133 } otMeshDiagRouterInfo; 134 135 /** 136 * Represents information about a discovered child in Thread mesh using `otMeshDiagDiscoverTopology()`. 137 */ 138 typedef struct otMeshDiagChildInfo 139 { 140 uint16_t mRloc16; ///< RLOC16. 141 otLinkModeConfig mMode; ///< Device mode. 142 uint8_t mLinkQuality; ///< Incoming link quality to child from parent. 143 bool mIsThisDevice : 1; ///< Whether child is this device itself. 144 bool mIsBorderRouter : 1; ///< Whether child acts as a border router providing ext connectivity. 145 } otMeshDiagChildInfo; 146 147 /** 148 * Pointer type represents the callback used by `otMeshDiagDiscoverTopology()` to provide information 149 * about a discovered router. 150 * 151 * When @p aError is `OT_ERROR_PENDING`, it indicates that the discovery is not yet finished and there will be more 152 * routers to discover and the callback will be invoked again. 153 * 154 * @param[in] aError OT_ERROR_PENDING Indicates there are more routers to be discovered. 155 * OT_ERROR_NONE Indicates this is the last router and mesh discovery is done. 156 * OT_ERROR_RESPONSE_TIMEOUT Timed out waiting for response from one or more routers. 157 * @param[in] aRouterInfo The discovered router info (can be null if `aError` is OT_ERROR_RESPONSE_TIMEOUT). 158 * @param[in] aContext Application-specific context. 159 */ 160 typedef void (*otMeshDiagDiscoverCallback)(otError aError, otMeshDiagRouterInfo *aRouterInfo, void *aContext); 161 162 /** 163 * Starts network topology discovery. 164 * 165 * @param[in] aInstance The OpenThread instance. 166 * @param[in] aConfig The configuration to use for discovery (e.g., which items to discover). 167 * @param[in] aCallback The callback to report the discovered routers. 168 * @param[in] aContext A context to pass in @p aCallback. 169 * 170 * @retval OT_ERROR_NONE The network topology discovery started successfully. 171 * @retval OT_ERROR_BUSY A previous discovery request is still ongoing. 172 * @retval OT_ERROR_INVALID_STATE Device is not attached. 173 * @retval OT_ERROR_NO_BUFS Could not allocate buffer to send discovery messages. 174 */ 175 otError otMeshDiagDiscoverTopology(otInstance *aInstance, 176 const otMeshDiagDiscoverConfig *aConfig, 177 otMeshDiagDiscoverCallback aCallback, 178 void *aContext); 179 180 /** 181 * Cancels an ongoing topology discovery if there is one, otherwise no action. 182 * 183 * When ongoing discovery is cancelled, the callback from `otMeshDiagDiscoverTopology()` will not be called anymore. 184 */ 185 void otMeshDiagCancel(otInstance *aInstance); 186 187 /** 188 * Iterates through the discovered IPv6 addresses of a router or an MTD child. 189 * 190 * MUST be used 191 * - from the callback `otMeshDiagDiscoverCallback()` and use the `mIp6AddrIterator` from the `aRouterInfo` struct that 192 * is provided as input to the callback, or 193 * - from the callback `otMeshDiagChildIp6AddrsCallback()` along with provided `aIp6AddrIterator`. 194 * 195 * @param[in,out] aIterator The address iterator to use. 196 * @param[out] aIp6Address A pointer to return the next IPv6 address (if any). 197 * 198 * @retval OT_ERROR_NONE Successfully retrieved the next address. @p aIp6Address and @p aIterator are updated. 199 * @retval OT_ERROR_NOT_FOUND No more address. Reached the end of the list. 200 */ 201 otError otMeshDiagGetNextIp6Address(otMeshDiagIp6AddrIterator *aIterator, otIp6Address *aIp6Address); 202 203 /** 204 * Iterates through the discovered children of a router. 205 * 206 * This function MUST be used from the callback `otMeshDiagDiscoverCallback()` and use the `mChildIterator` from the 207 * `aRouterInfo` struct that is provided as input to the callback. 208 * 209 * @param[in,out] aIterator The address iterator to use. 210 * @param[out] aChildInfo A pointer to return the child info (if any). 211 * 212 * @retval OT_ERROR_NONE Successfully retrieved the next child. @p aChildInfo and @p aIterator are updated. 213 * @retval OT_ERROR_NOT_FOUND No more child. Reached the end of the list. 214 */ 215 otError otMeshDiagGetNextChildInfo(otMeshDiagChildIterator *aIterator, otMeshDiagChildInfo *aChildInfo); 216 217 /** 218 * Represents information about a child entry from `otMeshDiagQueryChildTable()`. 219 * 220 * `mSupportsErrRate` indicates whether or not the error tracking feature is supported and `mFrameErrorRate` and 221 * `mMessageErrorRate` values are valid. The frame error rate tracks frame tx errors (towards the child) at MAC 222 * layer, while `mMessageErrorRate` tracks the IPv6 message error rate (above MAC layer and after MAC retries) when 223 * an IPv6 message is dropped. For example, if the message is large and requires 6LoWPAN fragmentation, message tx is 224 * considered as failed if one of its fragment frame tx fails (for example, never acked). 225 */ 226 typedef struct otMeshDiagChildEntry 227 { 228 bool mRxOnWhenIdle : 1; ///< Is rx-on when idle (vs sleepy). 229 bool mDeviceTypeFtd : 1; ///< Is device FTD (vs MTD). 230 bool mFullNetData : 1; ///< Whether device gets full Network Data (vs stable sub-set). 231 bool mCslSynchronized : 1; ///< Is CSL capable and CSL synchronized. 232 bool mSupportsErrRate : 1; ///< `mFrameErrorRate` and `mMessageErrorRate` values are valid. 233 uint16_t mRloc16; ///< RLOC16. 234 otExtAddress mExtAddress; ///< Extended Address. 235 uint16_t mVersion; ///< Version. 236 uint32_t mTimeout; ///< Timeout in seconds. 237 uint32_t mAge; ///< Seconds since last heard from the child. 238 uint32_t mConnectionTime; ///< Seconds since child attach. 239 uint16_t mSupervisionInterval; ///< Supervision interval in seconds. Zero to indicate not used. 240 uint8_t mLinkMargin; ///< Link Margin in dB. 241 int8_t mAverageRssi; ///< Average RSSI. 242 int8_t mLastRssi; ///< RSSI of last received frame. 243 uint16_t mFrameErrorRate; ///< Frame error rate (0x0000->0%, 0xffff->100%). 244 uint16_t mMessageErrorRate; ///< (IPv6) msg error rate (0x0000->0%, 0xffff->100%). 245 uint16_t mQueuedMessageCount; ///< Number of queued messages for indirect tx to child. 246 uint16_t mCslPeriod; ///< CSL Period in unit of 10-symbols-time. Zero indicates CSL is disabled. 247 uint32_t mCslTimeout; ///< CSL Timeout in seconds. 248 uint8_t mCslChannel; ///< CSL channel. 249 } otMeshDiagChildEntry; 250 251 /** 252 * Represents the callback used by `otMeshDiagQueryChildTable()` to provide information about child table entries. 253 * 254 * When @p aError is `OT_ERROR_PENDING`, it indicates that the table still has more entries and the callback will be 255 * invoked again. 256 * 257 * @param[in] aError OT_ERROR_PENDING Indicates there are more entries in the table. 258 * OT_ERROR_NONE Indicates the table is finished. 259 * OT_ERROR_RESPONSE_TIMEOUT Timed out waiting for response. 260 * @param[in] aChildEntry The child entry (can be null if `aError` is OT_ERROR_RESPONSE_TIMEOUT or OT_ERROR_NONE). 261 * @param[in] aContext Application-specific context. 262 */ 263 typedef void (*otMeshDiagQueryChildTableCallback)(otError aError, 264 const otMeshDiagChildEntry *aChildEntry, 265 void *aContext); 266 267 /** 268 * Starts query for child table for a given router. 269 * 270 * @param[in] aInstance The OpenThread instance. 271 * @param[in] aRloc16 The RLOC16 of router to query. 272 * @param[in] aCallback The callback to report the queried child table. 273 * @param[in] aContext A context to pass in @p aCallback. 274 * 275 * @retval OT_ERROR_NONE The query started successfully. 276 * @retval OT_ERROR_BUSY A previous discovery or query request is still ongoing. 277 * @retval OT_ERROR_INVALID_ARGS The @p aRloc16 is not a valid router RLOC16. 278 * @retval OT_ERROR_INVALID_STATE Device is not attached. 279 * @retval OT_ERROR_NO_BUFS Could not allocate buffer to send query messages. 280 */ 281 otError otMeshDiagQueryChildTable(otInstance *aInstance, 282 uint16_t aRloc16, 283 otMeshDiagQueryChildTableCallback aCallback, 284 void *aContext); 285 286 /** 287 * Represents the callback used by `otMeshDiagQueryChildrenIp6Addrs()` to provide information about an MTD child and 288 * its list of IPv6 addresses. 289 * 290 * When @p aError is `OT_ERROR_PENDING`, it indicates that there are more children and the callback will be invoked 291 * again. 292 * 293 * @param[in] aError OT_ERROR_PENDING Indicates there are more children in the table. 294 * OT_ERROR_NONE Indicates the table is finished. 295 * OT_ERROR_RESPONSE_TIMEOUT Timed out waiting for response. 296 * @param[in] aChildRloc16 The RLOC16 of the child. `0xfffe` is used on `OT_ERROR_RESPONSE_TIMEOUT`. 297 * @param[in] aIp6AddrIterator An iterator to go through the IPv6 addresses of the child with @p aRloc using 298 * `otMeshDiagGetNextIp6Address()`. Set to NULL on `OT_ERROR_RESPONSE_TIMEOUT`. 299 * @param[in] aContext Application-specific context. 300 */ 301 typedef void (*otMeshDiagChildIp6AddrsCallback)(otError aError, 302 uint16_t aChildRloc16, 303 otMeshDiagIp6AddrIterator *aIp6AddrIterator, 304 void *aContext); 305 306 /** 307 * Sends a query to a parent to retrieve the IPv6 addresses of all its MTD children. 308 * 309 * @param[in] aInstance The OpenThread instance. 310 * @param[in] aRloc16 The RLOC16 of parent to query. 311 * @param[in] aCallback The callback to report the queried child IPv6 address list. 312 * @param[in] aContext A context to pass in @p aCallback. 313 * 314 * @retval OT_ERROR_NONE The query started successfully. 315 * @retval OT_ERROR_BUSY A previous discovery or query request is still ongoing. 316 * @retval OT_ERROR_INVALID_ARGS The @p aRloc16 is not a valid RLOC16. 317 * @retval OT_ERROR_INVALID_STATE Device is not attached. 318 * @retval OT_ERROR_NO_BUFS Could not allocate buffer to send query messages. 319 */ 320 otError otMeshDiagQueryChildrenIp6Addrs(otInstance *aInstance, 321 uint16_t aRloc16, 322 otMeshDiagChildIp6AddrsCallback aCallback, 323 void *aContext); 324 325 /** 326 * Represents information about a router neighbor entry from `otMeshDiagQueryRouterNeighborTable()`. 327 * 328 * `mSupportsErrRate` indicates whether or not the error tracking feature is supported and `mFrameErrorRate` and 329 * `mMessageErrorRate` values are valid. The frame error rate tracks frame tx errors (towards the child) at MAC 330 * layer, while `mMessageErrorRate` tracks the IPv6 message error rate (above MAC layer and after MAC retries) when 331 * an IPv6 message is dropped. For example, if the message is large and requires 6LoWPAN fragmentation, message tx is 332 * considered as failed if one of its fragment frame tx fails (for example, never acked). 333 */ 334 typedef struct otMeshDiagRouterNeighborEntry 335 { 336 bool mSupportsErrRate : 1; ///< `mFrameErrorRate` and `mMessageErrorRate` values are valid. 337 uint16_t mRloc16; ///< RLOC16. 338 otExtAddress mExtAddress; ///< Extended Address. 339 uint16_t mVersion; ///< Version. 340 uint32_t mConnectionTime; ///< Seconds since link establishment. 341 uint8_t mLinkMargin; ///< Link Margin in dB. 342 int8_t mAverageRssi; ///< Average RSSI. 343 int8_t mLastRssi; ///< RSSI of last received frame. 344 uint16_t mFrameErrorRate; ///< Frame error rate (0x0000->0%, 0xffff->100%). 345 uint16_t mMessageErrorRate; ///< (IPv6) msg error rate (0x0000->0%, 0xffff->100%). 346 } otMeshDiagRouterNeighborEntry; 347 348 /** 349 * Represents the callback used by `otMeshDiagQueryRouterNeighborTable()` to provide information about neighbor router 350 * table entries. 351 * 352 * When @p aError is `OT_ERROR_PENDING`, it indicates that the table still has more entries and the callback will be 353 * invoked again. 354 * 355 * @param[in] aError OT_ERROR_PENDING Indicates there are more entries in the table. 356 * OT_ERROR_NONE Indicates the table is finished. 357 * OT_ERROR_RESPONSE_TIMEOUT Timed out waiting for response. 358 * @param[in] aNeighborEntry The neighbor entry (can be null if `aError` is RESPONSE_TIMEOUT or NONE). 359 * @param[in] aContext Application-specific context. 360 */ 361 typedef void (*otMeshDiagQueryRouterNeighborTableCallback)(otError aError, 362 const otMeshDiagRouterNeighborEntry *aNeighborEntry, 363 void *aContext); 364 365 /** 366 * Starts query for router neighbor table for a given router. 367 * 368 * @param[in] aInstance The OpenThread instance. 369 * @param[in] aRloc16 The RLOC16 of router to query. 370 * @param[in] aCallback The callback to report the queried table. 371 * @param[in] aContext A context to pass in @p aCallback. 372 * 373 * @retval OT_ERROR_NONE The query started successfully. 374 * @retval OT_ERROR_BUSY A previous discovery or query request is still ongoing. 375 * @retval OT_ERROR_INVALID_ARGS The @p aRloc16 is not a valid router RLOC16. 376 * @retval OT_ERROR_INVALID_STATE Device is not attached. 377 * @retval OT_ERROR_NO_BUFS Could not allocate buffer to send query messages. 378 */ 379 otError otMeshDiagQueryRouterNeighborTable(otInstance *aInstance, 380 uint16_t aRloc16, 381 otMeshDiagQueryRouterNeighborTableCallback aCallback, 382 void *aContext); 383 384 /** 385 * @} 386 */ 387 388 #ifdef __cplusplus 389 } // extern "C" 390 #endif 391 392 #endif // OPENTHREAD_MESH_DIAG_H_ 393