1 /*
2  *  Copyright (c) 2020, 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 Network Diagnostic API.
33  */
34 
35 #ifndef OPENTHREAD_NETDIAG_H_
36 #define OPENTHREAD_NETDIAG_H_
37 
38 #include <openthread/ip6.h>
39 #include <openthread/thread.h>
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 /**
46  * @addtogroup api-thread-general
47  *
48  * @{
49  *
50  */
51 
52 /**
53  * Maximum Number of Network Diagnostic TLV Types to Request or Reset.
54  */
55 #define OT_NETWORK_DIAGNOSTIC_TYPELIST_MAX_ENTRIES 19
56 
57 /**
58  * Size of Network Diagnostic Child Table entry.
59  */
60 #define OT_NETWORK_DIAGNOSTIC_CHILD_TABLE_ENTRY_SIZE 3
61 
62 /**
63  * Initializer for otNetworkDiagIterator.
64  */
65 #define OT_NETWORK_DIAGNOSTIC_ITERATOR_INIT 0
66 
67 enum
68 {
69     OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS          = 0,  ///< MAC Extended Address TLV
70     OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS        = 1,  ///< Address16 TLV
71     OT_NETWORK_DIAGNOSTIC_TLV_MODE                 = 2,  ///< Mode TLV
72     OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT              = 3,  ///< Timeout TLV (the maximum polling time period for SEDs)
73     OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY         = 4,  ///< Connectivity TLV
74     OT_NETWORK_DIAGNOSTIC_TLV_ROUTE                = 5,  ///< Route64 TLV
75     OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA          = 6,  ///< Leader Data TLV
76     OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA         = 7,  ///< Network Data TLV
77     OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST        = 8,  ///< IPv6 Address List TLV
78     OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS         = 9,  ///< MAC Counters TLV
79     OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL        = 14, ///< Battery Level TLV
80     OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE       = 15, ///< Supply Voltage TLV
81     OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE          = 16, ///< Child Table TLV
82     OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES        = 17, ///< Channel Pages TLV
83     OT_NETWORK_DIAGNOSTIC_TLV_TYPE_LIST            = 18, ///< Type List TLV
84     OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT    = 19, ///< Max Child Timeout TLV
85     OT_NETWORK_DIAGNOSTIC_TLV_VERSION              = 24, ///< Version TLV
86     OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_NAME          = 25, ///< Vendor Name TLV
87     OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_MODEL         = 26, ///< Vendor Model TLV
88     OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_SW_VERSION    = 27, ///< Vendor SW Version TLV
89     OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION = 28, ///< Thread Stack Version TLV
90     OT_NETWORK_DIAGNOSTIC_TLV_CHILD                = 29, ///< Child TLV
91     OT_NETWORK_DIAGNOSTIC_TLV_CHILD_IP6_ADDR_LIST  = 30, ///< Child IPv6 Address List TLV
92     OT_NETWORK_DIAGNOSTIC_TLV_ROUTER_NEIGHBOR      = 31, ///< Router Neighbor TLV
93     OT_NETWORK_DIAGNOSTIC_TLV_ANSWER               = 32, ///< Answer TLV
94     OT_NETWORK_DIAGNOSTIC_TLV_QUERY_ID             = 33, ///< Query ID TLV
95     OT_NETWORK_DIAGNOSTIC_TLV_MLE_COUNTERS         = 34, ///< MLE Counters TLV
96 
97 };
98 
99 #define OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_NAME_TLV_LENGTH 32          ///< Max length of Vendor Name TLV.
100 #define OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_MODEL_TLV_LENGTH 32         ///< Max length of Vendor Model TLV.
101 #define OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_SW_VERSION_TLV_LENGTH 16    ///< Max length of Vendor SW Version TLV.
102 #define OT_NETWORK_DIAGNOSTIC_MAX_THREAD_STACK_VERSION_TLV_LENGTH 64 ///< Max length of Thread Stack Version TLV.
103 
104 typedef uint16_t otNetworkDiagIterator; ///< Used to iterate through Network Diagnostic TLV.
105 
106 /**
107  * Represents a Network Diagnostic Connectivity value.
108  *
109  */
110 typedef struct otNetworkDiagConnectivity
111 {
112     /**
113      * The priority of the sender as a parent.
114      */
115     int8_t mParentPriority;
116 
117     /**
118      * The number of neighboring devices with which the sender shares a link of quality 3.
119      */
120     uint8_t mLinkQuality3;
121 
122     /**
123      * The number of neighboring devices with which the sender shares a link of quality 2.
124      */
125     uint8_t mLinkQuality2;
126 
127     /**
128      * The number of neighboring devices with which the sender shares a link of quality 1.
129      */
130     uint8_t mLinkQuality1;
131 
132     /**
133      * The sender's routing cost to the Leader.
134      */
135     uint8_t mLeaderCost;
136 
137     /**
138      * The most recent ID sequence number received by the sender.
139      */
140     uint8_t mIdSequence;
141 
142     /**
143      * The number of active Routers in the sender's Thread Network Partition.
144      */
145     uint8_t mActiveRouters;
146 
147     /**
148      * The guaranteed buffer capacity in octets for all IPv6 datagrams destined to a given SED. Optional.
149      */
150     uint16_t mSedBufferSize;
151 
152     /**
153      * The guaranteed queue capacity in number of IPv6 datagrams destined to a given SED. Optional.
154      */
155     uint8_t mSedDatagramCount;
156 } otNetworkDiagConnectivity;
157 
158 /**
159  * Represents a Network Diagnostic Route data.
160  *
161  */
162 typedef struct otNetworkDiagRouteData
163 {
164     uint8_t mRouterId;           ///< The Assigned Router ID.
165     uint8_t mLinkQualityOut : 2; ///< Link Quality Out.
166     uint8_t mLinkQualityIn : 2;  ///< Link Quality In.
167     uint8_t mRouteCost : 4;      ///< Routing Cost. Infinite routing cost is represented by value 0.
168 } otNetworkDiagRouteData;
169 
170 /**
171  * Represents a Network Diagnostic Route TLV value.
172  *
173  */
174 typedef struct otNetworkDiagRoute
175 {
176     /**
177      * The sequence number associated with the set of Router ID assignments in #mRouteData.
178      */
179     uint8_t mIdSequence;
180 
181     /**
182      * Number of elements in #mRouteData.
183      */
184     uint8_t mRouteCount;
185 
186     /**
187      * Link Quality and Routing Cost data.
188      */
189     otNetworkDiagRouteData mRouteData[OT_NETWORK_MAX_ROUTER_ID + 1];
190 } otNetworkDiagRoute;
191 
192 /**
193  * Represents a Network Diagnostic Mac Counters value.
194  *
195  * See <a href="https://www.ietf.org/rfc/rfc2863">RFC 2863</a> for definitions of member fields.
196  *
197  */
198 typedef struct otNetworkDiagMacCounters
199 {
200     uint32_t mIfInUnknownProtos;
201     uint32_t mIfInErrors;
202     uint32_t mIfOutErrors;
203     uint32_t mIfInUcastPkts;
204     uint32_t mIfInBroadcastPkts;
205     uint32_t mIfInDiscards;
206     uint32_t mIfOutUcastPkts;
207     uint32_t mIfOutBroadcastPkts;
208     uint32_t mIfOutDiscards;
209 } otNetworkDiagMacCounters;
210 
211 /**
212  * Represents a Network Diagnostics MLE Counters value.
213  *
214  */
215 typedef struct otNetworkDiagMleCounters
216 {
217     uint16_t mDisabledRole;                  ///< Number of times device entered disabled role.
218     uint16_t mDetachedRole;                  ///< Number of times device entered detached role.
219     uint16_t mChildRole;                     ///< Number of times device entered child role.
220     uint16_t mRouterRole;                    ///< Number of times device entered router role.
221     uint16_t mLeaderRole;                    ///< Number of times device entered leader role.
222     uint16_t mAttachAttempts;                ///< Number of attach attempts while device was detached.
223     uint16_t mPartitionIdChanges;            ///< Number of changes to partition ID.
224     uint16_t mBetterPartitionAttachAttempts; ///< Number of attempts to attach to a better partition.
225     uint16_t mParentChanges;                 ///< Number of time device changed its parent.
226     uint64_t mTrackedTime;                   ///< Milliseconds tracked by next counters (zero if not supported).
227     uint64_t mDisabledTime;                  ///< Milliseconds device has been in disabled role.
228     uint64_t mDetachedTime;                  ///< Milliseconds device has been in detached role.
229     uint64_t mChildTime;                     ///< Milliseconds device has been in child role.
230     uint64_t mRouterTime;                    ///< Milliseconds device has been in router role.
231     uint64_t mLeaderTime;                    ///< Milliseconds device has been in leader role.
232 } otNetworkDiagMleCounters;
233 
234 /**
235  * Represents a Network Diagnostic Child Table Entry.
236  *
237  */
238 typedef struct otNetworkDiagChildEntry
239 {
240     /**
241      * Expected poll time expressed as 2^(Timeout-4) seconds.
242      */
243     uint16_t mTimeout : 5;
244 
245     /**
246      * Link Quality In value in [0,3].
247      *
248      * Value 0 indicates that sender does not support the feature to provide link quality info.
249      *
250      */
251     uint8_t mLinkQuality : 2;
252 
253     /**
254      * Child ID from which an RLOC can be generated.
255      */
256     uint16_t mChildId : 9;
257 
258     /**
259      * Link mode bits.
260      */
261     otLinkModeConfig mMode;
262 } otNetworkDiagChildEntry;
263 
264 /**
265  * Represents a Network Diagnostic TLV.
266  *
267  */
268 typedef struct otNetworkDiagTlv
269 {
270     /**
271      * The Network Diagnostic TLV type.
272      */
273     uint8_t mType;
274 
275     union
276     {
277         otExtAddress              mExtAddress;
278         uint16_t                  mAddr16;
279         otLinkModeConfig          mMode;
280         uint32_t                  mTimeout;
281         otNetworkDiagConnectivity mConnectivity;
282         otNetworkDiagRoute        mRoute;
283         otLeaderData              mLeaderData;
284         otNetworkDiagMacCounters  mMacCounters;
285         otNetworkDiagMleCounters  mMleCounters;
286         uint8_t                   mBatteryLevel;
287         uint16_t                  mSupplyVoltage;
288         uint32_t                  mMaxChildTimeout;
289         uint16_t                  mVersion;
290         char                      mVendorName[OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_NAME_TLV_LENGTH + 1];
291         char                      mVendorModel[OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_MODEL_TLV_LENGTH + 1];
292         char                      mVendorSwVersion[OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_SW_VERSION_TLV_LENGTH + 1];
293         char                      mThreadStackVersion[OT_NETWORK_DIAGNOSTIC_MAX_THREAD_STACK_VERSION_TLV_LENGTH + 1];
294         struct
295         {
296             uint8_t mCount;
297             uint8_t m8[OT_NETWORK_BASE_TLV_MAX_LENGTH];
298         } mNetworkData;
299         struct
300         {
301             uint8_t      mCount;
302             otIp6Address mList[OT_NETWORK_BASE_TLV_MAX_LENGTH / OT_IP6_ADDRESS_SIZE];
303         } mIp6AddrList;
304         struct
305         {
306             uint8_t mCount;
307             otNetworkDiagChildEntry
308                 mTable[OT_NETWORK_BASE_TLV_MAX_LENGTH / OT_NETWORK_DIAGNOSTIC_CHILD_TABLE_ENTRY_SIZE];
309         } mChildTable;
310         struct
311         {
312             uint8_t mCount;
313             uint8_t m8[OT_NETWORK_BASE_TLV_MAX_LENGTH];
314         } mChannelPages;
315     } mData;
316 } otNetworkDiagTlv;
317 
318 /**
319  * Gets the next Network Diagnostic TLV in the message.
320  *
321  * Requires `OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE`.
322  *
323  * @param[in]      aMessage         A pointer to a message.
324  * @param[in,out]  aIterator        A pointer to the Network Diagnostic iterator context. To get the first
325  *                                  Network Diagnostic TLV it should be set to OT_NETWORK_DIAGNOSTIC_ITERATOR_INIT.
326  * @param[out]     aNetworkDiagTlv  A pointer to where the Network Diagnostic TLV information will be placed.
327  *
328  * @retval OT_ERROR_NONE       Successfully found the next Network Diagnostic TLV.
329  * @retval OT_ERROR_NOT_FOUND  No subsequent Network Diagnostic TLV exists in the message.
330  * @retval OT_ERROR_PARSE      Parsing the next Network Diagnostic failed.
331  *
332  * @Note A subsequent call to this function is allowed only when current return value is OT_ERROR_NONE.
333  *
334  */
335 otError otThreadGetNextDiagnosticTlv(const otMessage       *aMessage,
336                                      otNetworkDiagIterator *aIterator,
337                                      otNetworkDiagTlv      *aNetworkDiagTlv);
338 
339 /**
340  * Pointer is called when Network Diagnostic Get response is received.
341  *
342  * @param[in]  aError        The error when failed to get the response.
343  * @param[in]  aMessage      A pointer to the message buffer containing the received Network Diagnostic
344  *                           Get response payload. Available only when @p aError is `OT_ERROR_NONE`.
345  * @param[in]  aMessageInfo  A pointer to the message info for @p aMessage. Available only when
346  *                           @p aError is `OT_ERROR_NONE`.
347  * @param[in]  aContext      A pointer to application-specific context.
348  *
349  */
350 typedef void (*otReceiveDiagnosticGetCallback)(otError              aError,
351                                                otMessage           *aMessage,
352                                                const otMessageInfo *aMessageInfo,
353                                                void                *aContext);
354 
355 /**
356  * Send a Network Diagnostic Get request.
357  *
358  * Requires `OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE`.
359  *
360  * @param[in]  aInstance         A pointer to an OpenThread instance.
361  * @param[in]  aDestination      A pointer to destination address.
362  * @param[in]  aTlvTypes         An array of Network Diagnostic TLV types.
363  * @param[in]  aCount            Number of types in aTlvTypes.
364  * @param[in]  aCallback         A pointer to a function that is called when Network Diagnostic Get response
365  *                               is received or NULL to disable the callback.
366  * @param[in]  aCallbackContext  A pointer to application-specific context.
367  *
368  * @retval OT_ERROR_NONE    Successfully queued the DIAG_GET.req.
369  * @retval OT_ERROR_NO_BUFS Insufficient message buffers available to send DIAG_GET.req.
370  *
371  */
372 otError otThreadSendDiagnosticGet(otInstance                    *aInstance,
373                                   const otIp6Address            *aDestination,
374                                   const uint8_t                  aTlvTypes[],
375                                   uint8_t                        aCount,
376                                   otReceiveDiagnosticGetCallback aCallback,
377                                   void                          *aCallbackContext);
378 
379 /**
380  * Send a Network Diagnostic Reset request.
381  *
382  * Requires `OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE`.
383  *
384  * @param[in]  aInstance      A pointer to an OpenThread instance.
385  * @param[in]  aDestination   A pointer to destination address.
386  * @param[in]  aTlvTypes      An array of Network Diagnostic TLV types. Currently only Type 9 is allowed.
387  * @param[in]  aCount         Number of types in aTlvTypes
388  *
389  * @retval OT_ERROR_NONE    Successfully queued the DIAG_RST.ntf.
390  * @retval OT_ERROR_NO_BUFS Insufficient message buffers available to send DIAG_RST.ntf.
391  *
392  */
393 otError otThreadSendDiagnosticReset(otInstance         *aInstance,
394                                     const otIp6Address *aDestination,
395                                     const uint8_t       aTlvTypes[],
396                                     uint8_t             aCount);
397 
398 /**
399  * Get the vendor name string.
400  *
401  * @param[in]  aInstance      A pointer to an OpenThread instance.
402  *
403  * @returns The vendor name string.
404  *
405  */
406 const char *otThreadGetVendorName(otInstance *aInstance);
407 
408 /**
409  * Get the vendor model string.
410  *
411  * @param[in]  aInstance      A pointer to an OpenThread instance.
412  *
413  * @returns The vendor model string.
414  *
415  */
416 const char *otThreadGetVendorModel(otInstance *aInstance);
417 
418 /**
419  * Get the vendor sw version string.
420  *
421  * @param[in]  aInstance      A pointer to an OpenThread instance.
422  *
423  * @returns The vendor sw version string.
424  *
425  */
426 const char *otThreadGetVendorSwVersion(otInstance *aInstance);
427 
428 /**
429  * Set the vendor name string.
430  *
431  * Requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`.
432  *
433  * @p aVendorName should be UTF8 with max length of 32 chars (`MAX_VENDOR_NAME_TLV_LENGTH`). Maximum length does not
434  * include the null `\0` character.
435  *
436  * @param[in] aInstance       A pointer to an OpenThread instance.
437  * @param[in] aVendorName     The vendor name string.
438  *
439  * @retval OT_ERROR_NONE          Successfully set the vendor name.
440  * @retval OT_ERROR_INVALID_ARGS  @p aVendorName is not valid (too long or not UTF8).
441  *
442  */
443 otError otThreadSetVendorName(otInstance *aInstance, const char *aVendorName);
444 
445 /**
446  * Set the vendor model string.
447  *
448  * Requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`.
449  *
450  * @p aVendorModel should be UTF8 with max length of 32 chars (`MAX_VENDOR_MODEL_TLV_LENGTH`). Maximum length does not
451  * include the null `\0` character.
452  *
453  * @param[in] aInstance       A pointer to an OpenThread instance.
454  * @param[in] aVendorModel    The vendor model string.
455  *
456  * @retval OT_ERROR_NONE          Successfully set the vendor model.
457  * @retval OT_ERROR_INVALID_ARGS  @p aVendorModel is not valid (too long or not UTF8).
458  *
459  */
460 otError otThreadSetVendorModel(otInstance *aInstance, const char *aVendorModel);
461 
462 /**
463  * Set the vendor software version string.
464  *
465  * Requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`.
466  *
467  * @p aVendorSwVersion should be UTF8 with max length of 16 chars(`MAX_VENDOR_SW_VERSION_TLV_LENGTH`). Maximum length
468  * does not include the null `\0` character.
469  *
470  * @param[in] aInstance          A pointer to an OpenThread instance.
471  * @param[in] aVendorSwVersion   The vendor software version string.
472  *
473  * @retval OT_ERROR_NONE          Successfully set the vendor software version.
474  * @retval OT_ERROR_INVALID_ARGS  @p aVendorSwVersion is not valid (too long or not UTF8).
475  *
476  */
477 otError otThreadSetVendorSwVersion(otInstance *aInstance, const char *aVendorSwVersion);
478 
479 /**
480  * @}
481  *
482  */
483 
484 #ifdef __cplusplus
485 } // extern "C"
486 #endif
487 
488 #endif // OPENTHREAD_NETDIAG_H_
489