1 /*
2  *  Copyright (c) 2021, 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  */
26 
27 #ifndef OPENTHREAD_HISTORY_TRACKER_H_
28 #define OPENTHREAD_HISTORY_TRACKER_H_
29 
30 #include <openthread/instance.h>
31 #include <openthread/ip6.h>
32 #include <openthread/netdata.h>
33 #include <openthread/thread.h>
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 /**
40  * @addtogroup api-history-tracker
41  *
42  * @brief
43  *   Records the history of different events, for example RX and TX messages or network info changes. All tracked
44  *   entries are timestamped.
45  *
46  * The functions in this module are available when `OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE` is enabled.
47  *
48  * @{
49  *
50  */
51 
52 /**
53  * This constant specifies the maximum age of entries which is 49 days (in msec).
54  *
55  * Entries older than the max age will give this value as their age.
56  *
57  */
58 #define OT_HISTORY_TRACKER_MAX_AGE (49 * 24 * 60 * 60 * 1000u)
59 
60 #define OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE 21 ///< Recommended size for string representation of an entry age.
61 
62 /**
63  * Represents an iterator to iterate through a history list.
64  *
65  * The fields in this type are opaque (intended for use by OpenThread core) and therefore should not be accessed/used
66  * by caller.
67  *
68  * Before using an iterator, it MUST be initialized using `otHistoryTrackerInitIterator()`,
69  *
70  */
71 typedef struct otHistoryTrackerIterator
72 {
73     uint32_t mData32;
74     uint16_t mData16;
75 } otHistoryTrackerIterator;
76 
77 /**
78  * Represents Thread network info.
79  *
80  */
81 typedef struct otHistoryTrackerNetworkInfo
82 {
83     otDeviceRole     mRole;        ///< Device Role.
84     otLinkModeConfig mMode;        ///< Device Mode.
85     uint16_t         mRloc16;      ///< Device RLOC16.
86     uint32_t         mPartitionId; ///< Partition ID (valid when attached).
87 } otHistoryTrackerNetworkInfo;
88 
89 /**
90  * Defines the events for an IPv6 (unicast or multicast) address info (i.e., whether address is added
91  * or removed).
92  *
93  */
94 typedef enum
95 {
96     OT_HISTORY_TRACKER_ADDRESS_EVENT_ADDED   = 0, ///< Address is added.
97     OT_HISTORY_TRACKER_ADDRESS_EVENT_REMOVED = 1, ///< Address is removed.
98 } otHistoryTrackerAddressEvent;
99 
100 /**
101  * Represent a unicast IPv6 address info.
102  *
103  */
104 typedef struct otHistoryTrackerUnicastAddressInfo
105 {
106     otIp6Address                 mAddress;       ///< The unicast IPv6 address.
107     uint8_t                      mPrefixLength;  ///< The Prefix length (in bits).
108     uint8_t                      mAddressOrigin; ///< The address origin (`OT_ADDRESS_ORIGIN_*` constants).
109     otHistoryTrackerAddressEvent mEvent;         ///< Indicates the event (address is added/removed).
110     uint8_t                      mScope : 4;     ///< The IPv6 scope.
111     bool                         mPreferred : 1; ///< If the address is preferred.
112     bool                         mValid : 1;     ///< If the address is valid.
113     bool                         mRloc : 1;      ///< If the address is an RLOC.
114 } otHistoryTrackerUnicastAddressInfo;
115 
116 /**
117  * Represent an IPv6 multicast address info.
118  *
119  */
120 typedef struct otHistoryTrackerMulticastAddressInfo
121 {
122     otIp6Address                 mAddress;       ///< The IPv6 multicast address.
123     uint8_t                      mAddressOrigin; ///< The address origin (`OT_ADDRESS_ORIGIN_*` constants).
124     otHistoryTrackerAddressEvent mEvent;         ///< Indicates the event (address is added/removed).
125 } otHistoryTrackerMulticastAddressInfo;
126 
127 /**
128  * Constants representing message priority used in `otHistoryTrackerMessageInfo` struct.
129  *
130  */
131 enum
132 {
133     OT_HISTORY_TRACKER_MSG_PRIORITY_LOW    = OT_MESSAGE_PRIORITY_LOW,      ///< Low priority level.
134     OT_HISTORY_TRACKER_MSG_PRIORITY_NORMAL = OT_MESSAGE_PRIORITY_NORMAL,   ///< Normal priority level.
135     OT_HISTORY_TRACKER_MSG_PRIORITY_HIGH   = OT_MESSAGE_PRIORITY_HIGH,     ///< High priority level.
136     OT_HISTORY_TRACKER_MSG_PRIORITY_NET    = OT_MESSAGE_PRIORITY_HIGH + 1, ///< Network Control priority level.
137 };
138 
139 /**
140  * Represents a RX/TX IPv6 message info.
141  *
142  * Some of the fields in this struct are applicable to a RX message or a TX message only, e.g., `mAveRxRss` is the
143  * average RSS of all fragment frames that form a received message and is only applicable for a RX message.
144  *
145  */
146 typedef struct otHistoryTrackerMessageInfo
147 {
148     uint16_t   mPayloadLength;       ///< IPv6 payload length (exclude IP6 header itself).
149     uint16_t   mNeighborRloc16;      ///< RLOC16 of neighbor which sent/received the msg (`0xfffe` if no RLOC16).
150     otSockAddr mSource;              ///< Source IPv6 address and port (if UDP/TCP)
151     otSockAddr mDestination;         ///< Destination IPv6 address and port (if UDP/TCP).
152     uint16_t   mChecksum;            ///< Message checksum (valid only for UDP/TCP/ICMP6).
153     uint8_t    mIpProto;             ///< IP Protocol number (`OT_IP6_PROTO_*` enumeration).
154     uint8_t    mIcmp6Type;           ///< ICMP6 type if msg is ICMP6, zero otherwise (`OT_ICMP6_TYPE_*` enumeration).
155     int8_t     mAveRxRss;            ///< RSS of received message or OT_RADIO_INVALID_RSSI if not known.
156     bool       mLinkSecurity : 1;    ///< Indicates whether msg used link security.
157     bool       mTxSuccess : 1;       ///< Indicates TX success (e.g., ack received). Applicable for TX msg only.
158     uint8_t    mPriority : 2;        ///< Message priority (`OT_HISTORY_TRACKER_MSG_PRIORITY_*` enumeration).
159     bool       mRadioIeee802154 : 1; ///< Indicates whether msg was sent/received over a 15.4 radio link.
160     bool       mRadioTrelUdp6 : 1;   ///< Indicates whether msg was sent/received over a TREL radio link.
161 } otHistoryTrackerMessageInfo;
162 
163 /**
164  * Defines the events in a neighbor info (i.e. whether neighbor is added, removed, or changed).
165  *
166  * Event `OT_HISTORY_TRACKER_NEIGHBOR_EVENT_RESTORING` is applicable to child neighbors only. It is triggered after
167  * the device (re)starts and when the previous children list is retrieved from non-volatile settings and the device
168  * tries to restore connection to them.
169  *
170  */
171 typedef enum
172 {
173     OT_HISTORY_TRACKER_NEIGHBOR_EVENT_ADDED     = 0, ///< Neighbor is added.
174     OT_HISTORY_TRACKER_NEIGHBOR_EVENT_REMOVED   = 1, ///< Neighbor is removed.
175     OT_HISTORY_TRACKER_NEIGHBOR_EVENT_CHANGED   = 2, ///< Neighbor changed (e.g., device mode flags changed).
176     OT_HISTORY_TRACKER_NEIGHBOR_EVENT_RESTORING = 3, ///< Neighbor is being restored (applicable to child only).
177 } otHistoryTrackerNeighborEvent;
178 
179 /**
180  * Represents a neighbor info.
181  *
182  */
183 typedef struct otHistoryTrackerNeighborInfo
184 {
185     otExtAddress mExtAddress;           ///< Neighbor's Extended Address.
186     uint16_t     mRloc16;               ///< Neighbor's RLOC16.
187     int8_t       mAverageRssi;          ///< Average RSSI of rx frames from neighbor at the time of recording entry.
188     uint8_t      mEvent : 2;            ///< Indicates the event (`OT_HISTORY_TRACKER_NEIGHBOR_EVENT_*` enumeration).
189     bool         mRxOnWhenIdle : 1;     ///< Rx-on-when-idle.
190     bool         mFullThreadDevice : 1; ///< Full Thread Device.
191     bool         mFullNetworkData : 1;  ///< Full Network Data.
192     bool         mIsChild : 1;          ///< Indicates whether or not the neighbor is a child.
193 } otHistoryTrackerNeighborInfo;
194 
195 /**
196  * Defines the events in a router info (i.e. whether router is added, removed, or changed).
197  *
198  */
199 typedef enum
200 {
201     OT_HISTORY_TRACKER_ROUTER_EVENT_ADDED            = 0, ///< Router is added (router ID allocated).
202     OT_HISTORY_TRACKER_ROUTER_EVENT_REMOVED          = 1, ///< Router entry is removed (router ID released).
203     OT_HISTORY_TRACKER_ROUTER_EVENT_NEXT_HOP_CHANGED = 2, ///< Router entry next hop and cost changed.
204     OT_HISTORY_TRACKER_ROUTER_EVENT_COST_CHANGED     = 3, ///< Router entry path cost changed (next hop as before).
205 } otHistoryTrackerRouterEvent;
206 
207 #define OT_HISTORY_TRACKER_NO_NEXT_HOP 63 ///< No next hop - For `mNextHop` in `otHistoryTrackerRouterInfo`.
208 
209 #define OT_HISTORY_TRACKER_INFINITE_PATH_COST 0 ///< Infinite path cost - used in `otHistoryTrackerRouterInfo`.
210 
211 /**
212  * Represents a router table entry event.
213  *
214  */
215 typedef struct otHistoryTrackerRouterInfo
216 {
217     uint8_t mEvent : 2;       ///< Router entry event (`OT_HISTORY_TRACKER_ROUTER_EVENT_*` enumeration).
218     uint8_t mRouterId : 6;    ///< Router ID.
219     uint8_t mNextHop;         ///< Next Hop Router ID - `OT_HISTORY_TRACKER_NO_NEXT_HOP` if no next hop.
220     uint8_t mOldPathCost : 4; ///< Old path cost - `OT_HISTORY_TRACKER_INFINITE_PATH_COST` if infinite or unknown.
221     uint8_t mPathCost : 4;    ///< New path cost - `OT_HISTORY_TRACKER_INFINITE_PATH_COST` if infinite or unknown.
222 } otHistoryTrackerRouterInfo;
223 
224 /**
225  * Defines the events for a Network Data entry (i.e., whether an entry is added or removed).
226  *
227  */
228 typedef enum
229 {
230     OT_HISTORY_TRACKER_NET_DATA_ENTRY_ADDED   = 0, ///< Network data entry is added.
231     OT_HISTORY_TRACKER_NET_DATA_ENTRY_REMOVED = 1, ///< Network data entry is removed.
232 } otHistoryTrackerNetDataEvent;
233 
234 /**
235  * Represent a Network Data on mesh prefix info.
236  *
237  */
238 typedef struct otHistoryTrackerOnMeshPrefixInfo
239 {
240     otBorderRouterConfig         mPrefix; ///< The on mesh prefix entry.
241     otHistoryTrackerNetDataEvent mEvent;  ///< Indicates the event (added/removed).
242 } otHistoryTrackerOnMeshPrefixInfo;
243 
244 /**
245  * Represent a Network Data extern route info.
246  *
247  */
248 typedef struct otHistoryTrackerExternalRouteInfo
249 {
250     otExternalRouteConfig        mRoute; ///< The external route entry.
251     otHistoryTrackerNetDataEvent mEvent; ///< Indicates the event (added/removed).
252 } otHistoryTrackerExternalRouteInfo;
253 
254 /**
255  * Initializes an `otHistoryTrackerIterator`.
256  *
257  * An iterator MUST be initialized before it is used.
258  *
259  * An iterator can be initialized again to start from the beginning of the list.
260  *
261  * When iterating over entries in a list, to ensure the entry ages are consistent, the age is given relative to the
262  * time the iterator was initialized, i.e., the entry age is provided as the duration (in milliseconds) from the event
263  * (when entry was recorded) to the iterator initialization time.
264  *
265  * @param[in] aIterator  A pointer to the iterator to initialize (MUST NOT be NULL).
266  *
267  */
268 void otHistoryTrackerInitIterator(otHistoryTrackerIterator *aIterator);
269 
270 /**
271  * Iterates over the entries in the network info history list.
272  *
273  * @param[in]     aInstance   A pointer to the OpenThread instance.
274  * @param[in,out] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
275  * @param[out]    aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
276  *                            Age is provided as the duration (in milliseconds) from when entry was recorded to
277  *                            @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
278  *                            older than max age.
279  *
280  * @returns A pointer to `otHistoryTrackerNetworkInfo` entry or `NULL` if no more entries in the list.
281  *
282  */
283 const otHistoryTrackerNetworkInfo *otHistoryTrackerIterateNetInfoHistory(otInstance               *aInstance,
284                                                                          otHistoryTrackerIterator *aIterator,
285                                                                          uint32_t                 *aEntryAge);
286 
287 /**
288  * Iterates over the entries in the unicast address history list.
289  *
290  * @param[in]     aInstance  A pointer to the OpenThread instance.
291  * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
292  * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
293  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
294  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
295  *                           older than max age.
296  *
297  * @returns A pointer to `otHistoryTrackerUnicastAddressInfo` entry or `NULL` if no more entries in the list.
298  *
299  */
300 const otHistoryTrackerUnicastAddressInfo *otHistoryTrackerIterateUnicastAddressHistory(
301     otInstance               *aInstance,
302     otHistoryTrackerIterator *aIterator,
303     uint32_t                 *aEntryAge);
304 
305 /**
306  * Iterates over the entries in the multicast address history list.
307  *
308  * @param[in]     aInstance  A pointer to the OpenThread instance.
309  * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
310  * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
311  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
312  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
313  *                           older than max age.
314  *
315  * @returns A pointer to `otHistoryTrackerMulticastAddressInfo` entry or `NULL` if no more entries in the list.
316  *
317  */
318 const otHistoryTrackerMulticastAddressInfo *otHistoryTrackerIterateMulticastAddressHistory(
319     otInstance               *aInstance,
320     otHistoryTrackerIterator *aIterator,
321     uint32_t                 *aEntryAge);
322 
323 /**
324  * Iterates over the entries in the RX message history list.
325  *
326  * @param[in]     aInstance  A pointer to the OpenThread instance.
327  * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
328  * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
329  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
330  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
331  *                           older than max age.
332  *
333  * @returns The `otHistoryTrackerMessageInfo` entry or `NULL` if no more entries in the list.
334  *
335  */
336 const otHistoryTrackerMessageInfo *otHistoryTrackerIterateRxHistory(otInstance               *aInstance,
337                                                                     otHistoryTrackerIterator *aIterator,
338                                                                     uint32_t                 *aEntryAge);
339 
340 /**
341  * Iterates over the entries in the TX message history list.
342  *
343  * @param[in]     aInstance  A pointer to the OpenThread instance.
344  * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
345  * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
346  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
347  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
348  *                           older than max age.
349  *
350  * @returns The `otHistoryTrackerMessageInfo` entry or `NULL` if no more entries in the list.
351  *
352  */
353 const otHistoryTrackerMessageInfo *otHistoryTrackerIterateTxHistory(otInstance               *aInstance,
354                                                                     otHistoryTrackerIterator *aIterator,
355                                                                     uint32_t                 *aEntryAge);
356 
357 /**
358  * Iterates over the entries in the neighbor history list.
359  *
360  * @param[in]     aInstance  A pointer to the OpenThread instance.
361  * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
362  * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
363  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
364  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
365  *                           older than max age.
366  *
367  * @returns The `otHistoryTrackerNeighborInfo` entry or `NULL` if no more entries in the list.
368  *
369  */
370 const otHistoryTrackerNeighborInfo *otHistoryTrackerIterateNeighborHistory(otInstance               *aInstance,
371                                                                            otHistoryTrackerIterator *aIterator,
372                                                                            uint32_t                 *aEntryAge);
373 
374 /**
375  * Iterates over the entries in the router history list.
376  *
377  * @param[in]     aInstance  A pointer to the OpenThread instance.
378  * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
379  * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
380  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
381  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
382  *                           older than max age.
383  *
384  * @returns The `otHistoryTrackerRouterInfo` entry or `NULL` if no more entries in the list.
385  *
386  */
387 const otHistoryTrackerRouterInfo *otHistoryTrackerIterateRouterHistory(otInstance               *aInstance,
388                                                                        otHistoryTrackerIterator *aIterator,
389                                                                        uint32_t                 *aEntryAge);
390 
391 /**
392  * Iterates over the entries in the Network Data on mesh prefix entry history list.
393  *
394  * @param[in]     aInstance  A pointer to the OpenThread instance.
395  * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
396  * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
397  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
398  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
399  *                           older than max age.
400  *
401  * @returns The `otHistoryTrackerOnMeshPrefixInfo` entry or `NULL` if no more entries in the list.
402  *
403  */
404 const otHistoryTrackerOnMeshPrefixInfo *otHistoryTrackerIterateOnMeshPrefixHistory(otInstance               *aInstance,
405                                                                                    otHistoryTrackerIterator *aIterator,
406                                                                                    uint32_t                 *aEntryAge);
407 
408 /**
409  * Iterates over the entries in the Network Data external route entry history list.
410  *
411  * @param[in]     aInstance  A pointer to the OpenThread instance.
412  * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
413  * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
414  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
415  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
416  *                           older than max age.
417  *
418  * @returns The `otHistoryTrackerExternalRouteInfo` entry or `NULL` if no more entries in the list.
419  *
420  */
421 const otHistoryTrackerExternalRouteInfo *otHistoryTrackerIterateExternalRouteHistory(
422     otInstance               *aInstance,
423     otHistoryTrackerIterator *aIterator,
424     uint32_t                 *aEntryAge);
425 
426 /**
427  * Converts a given entry age to a human-readable string.
428  *
429  * The entry age string follows the format `hours:minutes:seconds:milliseconds` (if
430  * shorter than one day) or `days:hours:minutes:seconds`(if longer than one day).
431  *
432  * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be truncated
433  * but the outputted string is always null-terminated.
434  *
435  * @param[in]  aEntryAge The entry age (duration in msec).
436  * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be NULL).
437  * @param[in]  aSize     The size of @p aBuffer. Recommended to use `OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE`.
438  *
439  */
440 void otHistoryTrackerEntryAgeToString(uint32_t aEntryAge, char *aBuffer, uint16_t aSize);
441 
442 /**
443  * @}
444  *
445  */
446 
447 #ifdef __cplusplus
448 } // extern "C"
449 #endif
450 
451 #endif // OPENTHREAD_HISTORY_TRACKER_H_
452