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 Link Metrics API.
33  */
34 
35 #ifndef LINK_METRICS_H_
36 #define LINK_METRICS_H_
37 
38 #include <openthread/ip6.h>
39 #include <openthread/message.h>
40 #include <openthread/platform/radio.h>
41 
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
45 
46 /**
47  * @addtogroup api-link-metrics
48  *
49  * @brief
50  *   This module includes functions that control the Link Metrics protocol.
51  *
52  * @{
53  *
54  */
55 
56 /**
57  * Represents the result (value) for a Link Metrics query.
58  *
59  */
60 typedef struct otLinkMetricsValues
61 {
62     otLinkMetrics mMetrics; ///< Specifies which metrics values are present/included.
63 
64     uint32_t mPduCountValue;   ///< The value of Pdu Count.
65     uint8_t  mLqiValue;        ///< The value LQI.
66     uint8_t  mLinkMarginValue; ///< The value of Link Margin.
67     int8_t   mRssiValue;       ///< The value of Rssi.
68 } otLinkMetricsValues;
69 
70 /**
71  * Represents which frames are accounted in a Forward Tracking Series.
72  *
73  */
74 typedef struct otLinkMetricsSeriesFlags
75 {
76     bool mLinkProbe : 1;      ///< MLE Link Probe.
77     bool mMacData : 1;        ///< MAC Data frame.
78     bool mMacDataRequest : 1; ///< MAC Data Request.
79     bool mMacAck : 1;         ///< MAC Ack.
80 } otLinkMetricsSeriesFlags;
81 
82 /**
83  * Enhanced-ACK Flags.
84  *
85  * These are used in Enhanced-ACK Based Probing to indicate whether to register or clear the probing.
86  *
87  */
88 typedef enum otLinkMetricsEnhAckFlags
89 {
90     OT_LINK_METRICS_ENH_ACK_CLEAR    = 0, ///< Clear.
91     OT_LINK_METRICS_ENH_ACK_REGISTER = 1, ///< Register.
92 } otLinkMetricsEnhAckFlags;
93 
94 /**
95  * Link Metrics Status values.
96  *
97  */
98 typedef enum otLinkMetricsStatus
99 {
100     OT_LINK_METRICS_STATUS_SUCCESS                     = 0,
101     OT_LINK_METRICS_STATUS_CANNOT_SUPPORT_NEW_SERIES   = 1,
102     OT_LINK_METRICS_STATUS_SERIESID_ALREADY_REGISTERED = 2,
103     OT_LINK_METRICS_STATUS_SERIESID_NOT_RECOGNIZED     = 3,
104     OT_LINK_METRICS_STATUS_NO_MATCHING_FRAMES_RECEIVED = 4,
105     OT_LINK_METRICS_STATUS_OTHER_ERROR                 = 254,
106 } otLinkMetricsStatus;
107 
108 /**
109  * Pointer is called when a Link Metrics report is received.
110  *
111  * @param[in]  aSource         A pointer to the source address.
112  * @param[in]  aMetricsValues  A pointer to the Link Metrics values (the query result).
113  * @param[in]  aStatus         The status code in the report (only useful when @p aMetricsValues is NULL).
114  * @param[in]  aContext        A pointer to application-specific context.
115  *
116  */
117 typedef void (*otLinkMetricsReportCallback)(const otIp6Address        *aSource,
118                                             const otLinkMetricsValues *aMetricsValues,
119                                             otLinkMetricsStatus        aStatus,
120                                             void                      *aContext);
121 /**
122  * Pointer is called when a Link Metrics Management Response is received.
123  *
124  * @param[in]  aSource         A pointer to the source address.
125  * @param[in]  aStatus         The status code in the response.
126  * @param[in]  aContext        A pointer to application-specific context.
127  *
128  */
129 typedef void (*otLinkMetricsMgmtResponseCallback)(const otIp6Address *aSource,
130                                                   otLinkMetricsStatus aStatus,
131                                                   void               *aContext);
132 
133 /**
134  * Pointer is called when Enh-ACK Probing IE is received.
135  *
136  * @param[in] aShortAddress     The Mac short address of the Probing Subject.
137  * @param[in] aExtAddress       A pointer to the Mac extended address of the Probing Subject.
138  * @param[in] aMetricsValues    A pointer to the Link Metrics values obtained from the IE.
139  * @param[in] aContext          A pointer to application-specific context.
140  *
141  */
142 typedef void (*otLinkMetricsEnhAckProbingIeReportCallback)(otShortAddress             aShortAddress,
143                                                            const otExtAddress        *aExtAddress,
144                                                            const otLinkMetricsValues *aMetricsValues,
145                                                            void                      *aContext);
146 
147 /**
148  * Sends an MLE Data Request to query Link Metrics.
149  *
150  * It could be either Single Probe or Forward Tracking Series.
151  *
152  * @param[in]  aInstance            A pointer to an OpenThread instance.
153  * @param[in]  aDestination         A pointer to the destination address.
154  * @param[in]  aSeriesId            The Series ID to query about, 0 for Single Probe.
155  * @param[in]  aLinkMetricsFlags    A pointer to flags specifying what metrics to query.
156  * @param[in]  aCallback            A pointer to a function that is called when Link Metrics report is received.
157  * @param[in]  aCallbackContext     A pointer to application-specific context.
158  *
159  * @retval OT_ERROR_NONE              Successfully sent a Link Metrics query message.
160  * @retval OT_ERROR_NO_BUFS           Insufficient buffers to generate the MLE Data Request message.
161  * @retval OT_ERROR_UNKNOWN_NEIGHBOR  @p aDestination is not link-local or the neighbor is not found.
162  * @retval OT_ERROR_NOT_CAPABLE       The neighbor is not a Thread 1.2 device and does not support Link Metrics.
163  *
164  */
165 otError otLinkMetricsQuery(otInstance                 *aInstance,
166                            const otIp6Address         *aDestination,
167                            uint8_t                     aSeriesId,
168                            const otLinkMetrics        *aLinkMetricsFlags,
169                            otLinkMetricsReportCallback aCallback,
170                            void                       *aCallbackContext);
171 
172 /**
173  * Sends an MLE Link Metrics Management Request to configure or clear a Forward Tracking Series.
174  *
175  * @param[in] aInstance          A pointer to an OpenThread instance.
176  * @param[in] aDestination       A pointer to the destination address.
177  * @param[in] aSeriesId          The Series ID to operate with.
178  * @param[in] aSeriesFlags       The Series Flags that specifies which frames are to be accounted.
179  * @param[in] aLinkMetricsFlags  A pointer to flags specifying what metrics to query. Should be `NULL` when
180  *                               `aSeriesFlags` is `0`.
181  * @param[in]  aCallback         A pointer to a function that is called when Link Metrics Management Response is
182  *                               received.
183  * @param[in]  aCallbackContext  A pointer to application-specific context.
184  *
185  * @retval OT_ERROR_NONE              Successfully sent a Link Metrics Management Request message.
186  * @retval OT_ERROR_NO_BUFS           Insufficient buffers to generate the MLE Link Metrics Management Request message.
187  * @retval OT_ERROR_INVALID_ARGS      @p aSeriesId is not within the valid range.
188  * @retval OT_ERROR_UNKNOWN_NEIGHBOR  @p aDestination is not link-local or the neighbor is not found.
189  * @retval OT_ERROR_NOT_CAPABLE       The neighbor is not a Thread 1.2 device and does not support Link Metrics.
190  *
191  */
192 otError otLinkMetricsConfigForwardTrackingSeries(otInstance                       *aInstance,
193                                                  const otIp6Address               *aDestination,
194                                                  uint8_t                           aSeriesId,
195                                                  otLinkMetricsSeriesFlags          aSeriesFlags,
196                                                  const otLinkMetrics              *aLinkMetricsFlags,
197                                                  otLinkMetricsMgmtResponseCallback aCallback,
198                                                  void                             *aCallbackContext);
199 
200 /**
201  * Sends an MLE Link Metrics Management Request to configure/clear an Enhanced-ACK Based Probing.
202  * This functionality requires OT_LINK_METRICS_INITIATOR feature enabled.
203  *
204  * @param[in] aInstance          A pointer to an OpenThread instance.
205  * @param[in] aDestination       A pointer to the destination address.
206  * @param[in] aEnhAckFlags       Enh-ACK Flags to indicate whether to register or clear the probing. `0` to clear and
207  *                               `1` to register. Other values are reserved.
208  * @param[in] aLinkMetricsFlags  A pointer to flags specifying what metrics to query. Should be `NULL` when
209  *                               `aEnhAckFlags` is `0`.
210  * @param[in] aCallback          A pointer to a function that is called when an Enhanced Ack with Link Metrics is
211  *                               received.
212  * @param[in] aCallbackContext   A pointer to application-specific context.
213  *
214  * @retval OT_ERROR_NONE              Successfully sent a Link Metrics Management Request message.
215  * @retval OT_ERROR_NO_BUFS           Insufficient buffers to generate the MLE Link Metrics Management Request message.
216  * @retval OT_ERROR_INVALID_ARGS      @p aEnhAckFlags is not a valid value or @p aLinkMetricsFlags isn't correct.
217  * @retval OT_ERROR_UNKNOWN_NEIGHBOR  @p aDestination is not link-local or the neighbor is not found.
218  * @retval OT_ERROR_NOT_CAPABLE       The neighbor is not a Thread 1.2 device and does not support Link Metrics.
219  *
220  */
221 otError otLinkMetricsConfigEnhAckProbing(otInstance                                *aInstance,
222                                          const otIp6Address                        *aDestination,
223                                          otLinkMetricsEnhAckFlags                   aEnhAckFlags,
224                                          const otLinkMetrics                       *aLinkMetricsFlags,
225                                          otLinkMetricsMgmtResponseCallback          aCallback,
226                                          void                                      *aCallbackContext,
227                                          otLinkMetricsEnhAckProbingIeReportCallback aEnhAckCallback,
228                                          void                                      *aEnhAckCallbackContext);
229 
230 /**
231  * Sends an MLE Link Probe message.
232  *
233  * @param[in] aInstance       A pointer to an OpenThread instance.
234  * @param[in] aDestination    A pointer to the destination address.
235  * @param[in] aSeriesId       The Series ID [1, 254] which the Probe message aims at.
236  * @param[in] aLength         The length of the data payload in Link Probe TLV, [0, 64] (per Thread 1.2 spec, 4.4.37).
237  *
238  * @retval OT_ERROR_NONE              Successfully sent a Link Probe message.
239  * @retval OT_ERROR_NO_BUFS           Insufficient buffers to generate the MLE Link Probe message.
240  * @retval OT_ERROR_INVALID_ARGS      @p aSeriesId or @p aLength is not within the valid range.
241  * @retval OT_ERROR_UNKNOWN_NEIGHBOR  @p aDestination is not link-local or the neighbor is not found.
242  * @retval OT_ERROR_NOT_CAPABLE       The neighbor is not a Thread 1.2 device and does not support Link Metrics.
243  *
244  */
245 otError otLinkMetricsSendLinkProbe(otInstance         *aInstance,
246                                    const otIp6Address *aDestination,
247                                    uint8_t             aSeriesId,
248                                    uint8_t             aLength);
249 
250 /**
251  * Enable or disable Link Metrics Manager.
252  *
253  * @param[in] aInstance       A pointer to an OpenThread instance.
254  * @param[in] aEnable         A boolean indicating to enable or disable.
255  *
256  */
257 void otLinkMetricsManagerSetEnabled(otInstance *aInstance, bool aEnable);
258 
259 /**
260  * Get Link Metrics data of a neighbor by its extended address.
261  *
262  * @param[in]  aInstance           A pointer to an OpenThread instance.
263  * @param[in]  aExtAddress         A pointer to the Mac extended address of the Probing Subject.
264  * @param[out] aLinkMetricsValues  A pointer to the Link Metrics values of the subject.
265  *
266  * @retval OT_ERROR_NONE              Successfully got the Link Metrics data.
267  * @retval OT_ERROR_INVALID_ARGS      The arguments are invalid.
268  * @retval OT_ERROR_NOT_FOUND         No neighbor with the given extended address is found.
269  *
270  */
271 otError otLinkMetricsManagerGetMetricsValueByExtAddr(otInstance          *aInstance,
272                                                      const otExtAddress  *aExtAddress,
273                                                      otLinkMetricsValues *aLinkMetricsValues);
274 
275 /**
276  * @}
277  *
278  */
279 
280 #ifdef __cplusplus
281 } // extern "C"
282 #endif
283 
284 #endif // LINK_METRICS_H_
285