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/thread.h>
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 /**
39  * @addtogroup api-history-tracker
40  *
41  * @{
42  *
43  */
44 
45 /**
46  * @brief
47  *   This header defines the public API for History Tracker.
48  *
49  *   History Tracker module records history of different events (e.g. RX and TX messages or network info changes, etc.)
50  *   as the Thread network operates. All tracked entries are timestamped.
51  *
52  *   The functions in this module are available when `OPENTHREAD_CONFIG_HISTOR_TRACKER_ENABLE` is enabled.
53  *
54  */
55 
56 /**
57  * This constant specifies the maximum age of entries which is 49 days (in msec).
58  *
59  * Entries older than the max age will give this value as their age.
60  *
61  */
62 #define OT_HISTORY_TRACKER_MAX_AGE (49 * 24 * 60 * 60 * 1000u)
63 
64 #define OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE 21 ///< Recommended size for string representation of an entry age.
65 
66 /**
67  * This type represents an iterator to iterate through a history list.
68  *
69  * The fields in this type are opaque (intended for use by OpenThread core) and therefore should not be accessed/used
70  * by caller.
71  *
72  * Before using an iterator, it MUST be initialized using `otHistoryTrackerInitIterator()`,
73  *
74  */
75 typedef struct otHistoryTrackerIterator
76 {
77     uint32_t mData32;
78     uint16_t mData16;
79 } otHistoryTrackerIterator;
80 
81 /**
82  * This structure represents Thread network info.
83  *
84  */
85 typedef struct otHistoryTrackerNetworkInfo
86 {
87     otDeviceRole     mRole;        ///< Device Role.
88     otLinkModeConfig mMode;        ///< Device Mode.
89     uint16_t         mRloc16;      ///< Device RLOC16.
90     uint32_t         mPartitionId; ///< Partition ID (valid when attached).
91 } otHistoryTrackerNetworkInfo;
92 
93 /**
94  * Constants representing message priority used in `otHistoryTrackerMessageInfo` struct.
95  *
96  */
97 enum
98 {
99     OT_HISTORY_TRACKER_MSG_PRIORITY_LOW    = OT_MESSAGE_PRIORITY_LOW,      ///< Low priority level.
100     OT_HISTORY_TRACKER_MSG_PRIORITY_NORMAL = OT_MESSAGE_PRIORITY_NORMAL,   ///< Normal priority level.
101     OT_HISTORY_TRACKER_MSG_PRIORITY_HIGH   = OT_MESSAGE_PRIORITY_HIGH,     ///< High priority level.
102     OT_HISTORY_TRACKER_MSG_PRIORITY_NET    = OT_MESSAGE_PRIORITY_HIGH + 1, ///< Network Control priority level.
103 };
104 
105 /**
106  * This structure represents a RX/TX IPv6 message info.
107  *
108  * Some of the fields in this struct are applicable to a RX message or a TX message only, e.g., `mAveRxRss` is the
109  * average RSS of all fragment frames that form a received message and is only applicable for a RX message.
110  *
111  */
112 typedef struct otHistoryTrackerMessageInfo
113 {
114     uint16_t   mPayloadLength;       ///< IPv6 payload length (exclude IP6 header itself).
115     uint16_t   mNeighborRloc16;      ///< RLOC16 of neighbor which sent/received the msg (`0xfffe` if no RLOC16).
116     otSockAddr mSource;              ///< Source IPv6 address and port (if UDP/TCP)
117     otSockAddr mDestination;         ///< Destination IPv6 address and port (if UDP/TCP).
118     uint16_t   mChecksum;            ///< Message checksum (valid only for UDP/TCP/ICMP6).
119     uint8_t    mIpProto;             ///< IP Protocol number (`OT_IP6_PROTO_*` enumeration).
120     uint8_t    mIcmp6Type;           ///< ICMP6 type if msg is ICMP6, zero otherwise (`OT_ICMP6_TYPE_*` enumeration).
121     int8_t     mAveRxRss;            ///< RSS of received message or OT_RADIO_INVALI_RSSI if not known.
122     bool       mLinkSecurity : 1;    ///< Indicates whether msg used link security.
123     bool       mTxSuccess : 1;       ///< Indicates TX success (e.g., ack received). Applicable for TX msg only.
124     uint8_t    mPriority : 2;        ///< Message priority (`OT_HISTORY_TRACKER_MSG_PRIORITY_*` enumeration).
125     bool       mRadioIeee802154 : 1; ///< Indicates whether msg was sent/received over a 15.4 radio link.
126     bool       mRadioTrelUdp6 : 1;   ///< Indicates whether msg was sent/received over a TREL radio link.
127 } otHistoryTrackerMessageInfo;
128 
129 /**
130  * This enumeration defines the events in a neighbor info (i.e. whether neighbor is added, removed, or changed).
131  *
132  * Event `OT_HISTORY_TRACKER_NEIGHBOR_EVENT_RESTORING` is applicable to child neighbors only. It is triggered after
133  * the device (re)starts and when the previous children list is retrieved from non-volatile settings and the device
134  * tries to restore connection to them.
135  *
136  */
137 typedef enum
138 {
139     OT_HISTORY_TRACKER_NEIGHBOR_EVENT_ADDED     = 0, ///< Neighbor is added.
140     OT_HISTORY_TRACKER_NEIGHBOR_EVENT_REMOVED   = 1, ///< Neighbor is removed.
141     OT_HISTORY_TRACKER_NEIGHBOR_EVENT_CHANGED   = 2, ///< Neighbor changed (e.g., device mode flags changed).
142     OT_HISTORY_TRACKER_NEIGHBOR_EVENT_RESTORING = 3, ///< Neighbor is being restored (applicable to child only).
143 } otHistoryTrackerNeighborEvent;
144 
145 /**
146  * This structure represents a neighbor info.
147  *
148  */
149 typedef struct otHistoryTrackerNeighborInfo
150 {
151     otExtAddress mExtAddress;           ///< Neighbor's Extended Address.
152     uint16_t     mRloc16;               ///< Neighbor's RLOC16.
153     int8_t       mAverageRssi;          ///< Average RSSI of rx frames from neighbor at the time of recording entry.
154     uint8_t      mEvent : 2;            ///< Indicates the event (`OT_HISTORY_TRACKER_NEIGHBOR_EVENT_*` enumeration).
155     bool         mRxOnWhenIdle : 1;     ///< Rx-on-when-idle.
156     bool         mFullThreadDevice : 1; ///< Full Thread Device.
157     bool         mFullNetworkData : 1;  ///< Full Network Data.
158     bool         mIsChild : 1;          ///< Indicates whether or not the neighbor is a child.
159 } otHistoryTrackerNeighborInfo;
160 
161 /**
162  * This function initializes an `otHistoryTrackerIterator`.
163  *
164  * An iterator MUST be initialized before it is used.
165  *
166  * An iterator can be initialized again to start from the beginning of the list.
167  *
168  * When iterating over entries in a list, to ensure the entry ages are consistent, the age is given relative to the
169  * time the iterator was initialized, i.e., the entry age is provided as the duration (in milliseconds) from the event
170  * (when entry was recorded) to the iterator initialization time.
171  *
172  * @param[in] aIterator  A pointer to the iterator to initialize (MUST NOT be NULL).
173  *
174  */
175 void otHistoryTrackerInitIterator(otHistoryTrackerIterator *aIterator);
176 
177 /**
178  * This function iterates over the entries in the network info history list.
179  *
180  * @param[in]    aInstance   A pointer to the OpenThread instance.
181  * @param[inout] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
182  * @param[out]   aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
183  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
184  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
185  *                           older than max age.
186  *
187  * @returns A pointer to `otHistoryTrackerNetworkInfo` entry or `NULL` if no more entries in the list.
188  *
189  */
190 const otHistoryTrackerNetworkInfo *otHistoryTrackerIterateNetInfoHistory(otInstance *              aInstance,
191                                                                          otHistoryTrackerIterator *aIterator,
192                                                                          uint32_t *                aEntryAge);
193 
194 /**
195  * This function iterates over the entries in the RX message history list.
196  *
197  * @param[in]    aInstance   A pointer to the OpenThread instance.
198  * @param[inout] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
199  * @param[out]   aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
200  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
201  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
202  *                           older than max age.
203  *
204  * @returns The `otHistoryTrackerMessageInfo` entry or `NULL` if no more entries in the list.
205  *
206  */
207 const otHistoryTrackerMessageInfo *otHistoryTrackerIterateRxHistory(otInstance *              aInstance,
208                                                                     otHistoryTrackerIterator *aIterator,
209                                                                     uint32_t *                aEntryAge);
210 
211 /**
212  * This function iterates over the entries in the TX message history list.
213  *
214  * @param[in]    aInstance   A pointer to the OpenThread instance.
215  * @param[inout] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
216  * @param[out]   aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
217  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
218  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
219  *                           older than max age.
220  *
221  * @returns The `otHistoryTrackerMessageInfo` entry or `NULL` if no more entries in the list.
222  *
223  */
224 const otHistoryTrackerMessageInfo *otHistoryTrackerIterateTxHistory(otInstance *              aInstance,
225                                                                     otHistoryTrackerIterator *aIterator,
226                                                                     uint32_t *                aEntryAge);
227 
228 /**
229  * This function iterates over the entries in the neighbor history list.
230  *
231  * @param[in]    aInstance   A pointer to the OpenThread instance.
232  * @param[inout] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
233  * @param[out]   aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
234  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
235  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
236  *                           older than max age.
237  *
238  * @returns The `otHistoryTrackerNeighborInfo` entry or `NULL` if no more entries in the list.
239  *
240  */
241 const otHistoryTrackerNeighborInfo *otHistoryTrackerIterateNeighborHistory(otInstance *              aInstance,
242                                                                            otHistoryTrackerIterator *aIterator,
243                                                                            uint32_t *                aEntryAge);
244 
245 /**
246  * This function converts a given entry age to a human-readable string.
247  *
248  * The entry age string follows the format "<hh>:<mm>:<ss>.<mmmm>" for hours, minutes, seconds and millisecond (if
249  * shorter than one day) or "<dd> days <hh>:<mm>:<ss>.<mmmm>" (if longer than one day).
250  *
251  * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be truncated
252  * but the outputted string is always null-terminated.
253  *
254  * @param[in]  aEntryAge The entry age (duration in msec).
255  * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be NULL).
256  * @param[in]  aSize     The size of @p aBuffer. Recommended to use `OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE`.
257  *
258  */
259 void otHistoryTrackerEntryAgeToString(uint32_t aEntryAge, char *aBuffer, uint16_t aSize);
260 
261 /**
262  * @}
263  *
264  */
265 
266 #ifdef __cplusplus
267 } // extern "C"
268 #endif
269 
270 #endif // OPENTHREAD_HISTORY_TRACKER_H_
271