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