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 /**
58  * This structure represents the set of configurations used when discovering mesh topology indicating which items to
59  * discover.
60  *
61  */
62 typedef struct otMeshDiagDiscoverConfig
63 {
64     bool mDiscoverIp6Addresses : 1; ///< Whether or not to discover IPv6 addresses of every router.
65     bool mDiscoverChildTable : 1;   ///< Whether or not to discover children of every router.
66 } otMeshDiagDiscoverConfig;
67 
68 /**
69  * This type is an opaque iterator to iterate over list of IPv6 addresses of a router.
70  *
71  * Pointers to instance of this type are provided in `otMeshDiagRouterInfo`.
72  *
73  */
74 typedef struct otMeshDiagIp6AddrIterator otMeshDiagIp6AddrIterator;
75 
76 /**
77  * This type is an opaque iterator to iterate over list of children of a router.
78  *
79  * Pointers to instance of this type are provided in `otMeshDiagRouterInfo`.
80  *
81  */
82 typedef struct otMeshDiagChildIterator otMeshDiagChildIterator;
83 
84 /**
85  * This constant indicates that Thread Version is unknown.
86  *
87  * This is used in `otMeshDiagRouterInfo` for `mVersion` property when device does not provide its version. This
88  * indicates that device is likely running 1.3.0 (version value 4) or earlier.
89  *
90  */
91 #define OT_MESH_DIAG_VERSION_UNKNOWN 0xffff
92 
93 /**
94  * This type represents information about a router in Thread mesh.
95  *
96  */
97 typedef struct otMeshDiagRouterInfo
98 {
99     otExtAddress mExtAddress;             ///< Extended MAC address.
100     uint16_t     mRloc16;                 ///< RLOC16.
101     uint8_t      mRouterId;               ///< Router ID.
102     uint16_t     mVersion;                ///< Thread Version. `OT_MESH_DIAG_VERSION_UNKNOWN` if unknown.
103     bool         mIsThisDevice : 1;       ///< Whether router is this device itself.
104     bool         mIsThisDeviceParent : 1; ///< Whether router is parent of this device (when device is a child).
105     bool         mIsLeader : 1;           ///< Whether router is leader.
106     bool         mIsBorderRouter : 1;     ///< Whether router acts as a border router providing ext connectivity.
107 
108     /**
109      * This array provides the link quality from this router to other routers, also indicating whether a link is
110      * established between the routers.
111      *
112      * The array is indexed based on Router ID. `mLinkQualities[routerId]` indicates the incoming link quality, the
113      * router sees to the router with `routerId`. Link quality is a value in [0, 3]. Value zero indicates no link.
114      * Larger value indicate better link quality (as defined by Thread specification).
115      *
116      */
117     uint8_t mLinkQualities[OT_NETWORK_MAX_ROUTER_ID + 1];
118 
119     /**
120      * A pointer to an iterator to go through the list of IPv6 addresses of the router.
121      *
122      * The pointer is valid only while `otMeshDiagRouterInfo` is valid. It can be used in `otMeshDiagGetNextIp6Address`
123      * to iterate through the IPv6 addresses.
124      *
125      * The pointer can be NULL when there was no request to discover IPv6 addresses (in `otMeshDiagDiscoverConfig`) or
126      * if the router did not provide the list.
127      *
128      */
129     otMeshDiagIp6AddrIterator *mIp6AddrIterator;
130 
131     /**
132      * A pointer to an iterator to go through the list of children of the router.
133      *
134      * The pointer is valid only while `otMeshDiagRouterInfo` is valid. It can be used in `otMeshDiagGetNextChildInfo`
135      * to iterate through the children of the router.
136      *
137      * The pointer can be NULL when there was no request to discover children (in `otMeshDiagDiscoverConfig`) or
138      * if the router did not provide the list.
139      *
140      */
141     otMeshDiagChildIterator *mChildIterator;
142 } otMeshDiagRouterInfo;
143 
144 /**
145  * This type represents information about a discovered child in Thread mesh.
146  *
147  */
148 typedef struct otMeshDiagChildInfo
149 {
150     uint16_t         mRloc16;             ///< RLOC16.
151     otLinkModeConfig mMode;               ///< Device mode.
152     uint8_t          mLinkQuality;        ///< Incoming link quality to child from parent.
153     bool             mIsThisDevice : 1;   ///< Whether child is this device itself.
154     bool             mIsBorderRouter : 1; ///< Whether child acts as a border router providing ext connectivity.
155 } otMeshDiagChildInfo;
156 
157 /**
158  * This function pointer type represents the callback used by `otMeshDiagDiscoverTopology()` to provide information
159  * about a discovered router.
160  *
161  * When @p aError is `OT_ERROR_PENDING`, it indicates that the discovery is not yet finished and there will be more
162  * routers to discover and the callback will be invoked again.
163  *
164  * @param[in] aError       OT_ERROR_PENDING            Indicates there are more routers to be discovered.
165  *                         OT_ERROR_NONE               Indicates this is the last router and mesh discovery is done.
166  *                         OT_ERROR_RESPONSE_TIMEOUT   Timed out waiting for response from one or more routers.
167  * @param[in] aRouterInfo  The discovered router info (can be null if `aError` is OT_ERROR_RESPONSE_TIMEOUT).
168  * @param[in] aContext     Application-specific context.
169  *
170  */
171 typedef void (*otMeshDiagDiscoverCallback)(otError aError, otMeshDiagRouterInfo *aRouterInfo, void *aContext);
172 
173 /**
174  * This function starts network topology discovery.
175  *
176  * @param[in] aInstance        The OpenThread instance.
177  * @param[in] aConfig          The configuration to use for discovery (e.g., which items to discover).
178  * @param[in] aCallback        The callback to report the discovered routers.
179  * @param[in] aContext         A context to pass in @p aCallback.
180  *
181  * @retval OT_ERROR_NONE            The network topology discovery started successfully.
182  * @retval OT_ERROR_BUSY            A previous discovery request is still ongoing.
183  * @retval OT_ERROR_INVALID_STATE   Device is not attached.
184  * @retval OT_ERROR_NO_BUFS         Could not allocate buffer to send discovery messages.
185  *
186  */
187 otError otMeshDiagDiscoverTopology(otInstance                     *aInstance,
188                                    const otMeshDiagDiscoverConfig *aConfig,
189                                    otMeshDiagDiscoverCallback      aCallback,
190                                    void                           *aContext);
191 
192 /**
193  * This function cancels an ongoing topology discovery if there is one, otherwise no action.
194  *
195  * When ongoing discovery is cancelled, the callback from `otMeshDiagDiscoverTopology()` will not be called anymore.
196  *
197  */
198 void otMeshDiagCancel(otInstance *aInstance);
199 
200 /**
201  * This function iterates through the discovered IPv6 address of a router.
202  *
203  * @param[in,out]  aIterator    The address iterator to use.
204  * @param[out]     aIp6Address  A pointer to return the next IPv6 address (if any).
205  *
206  * @retval OT_ERROR_NONE       Successfully retrieved the next address. @p aIp6Address and @p aIterator are updated.
207  * @retval OT_ERROR_NOT_FOUND  No more address. Reached the end of the list.
208  *
209  */
210 otError otMeshDiagGetNextIp6Address(otMeshDiagIp6AddrIterator *aIterator, otIp6Address *aIp6Address);
211 
212 /**
213  * This function iterates through the discovered children of a router.
214  *
215  * @param[in,out]  aIterator    The address iterator to use.
216  * @param[out]     aChildInfo   A pointer to return the child info (if any).
217  *
218  * @retval OT_ERROR_NONE       Successfully retrieved the next child. @p aChildInfo and @p aIterator are updated.
219  * @retval OT_ERROR_NOT_FOUND  No more child. Reached the end of the list.
220  *
221  */
222 otError otMeshDiagGetNextChildInfo(otMeshDiagChildIterator *aIterator, otMeshDiagChildInfo *aChildInfo);
223 
224 /**
225  * @}
226  *
227  */
228 
229 #ifdef __cplusplus
230 } // extern "C"
231 #endif
232 
233 #endif // OPENTHREAD_MESH_DIAG_H_
234