• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  *   This file includes definitions for Thread Link Metrics query and management.
32  */
33 
34 #ifndef LINK_METRICS_HPP_
35 #define LINK_METRICS_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
40 
41 #if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
42 #error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE" \
43        "and OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE."
44 #endif
45 
46 #include <openthread/link.h>
47 #include <openthread/link_metrics.h>
48 
49 #include "common/as_core_type.hpp"
50 #include "common/callback.hpp"
51 #include "common/clearable.hpp"
52 #include "common/locator.hpp"
53 #include "common/message.hpp"
54 #include "common/non_copyable.hpp"
55 #include "common/pool.hpp"
56 #include "net/ip6_address.hpp"
57 #include "thread/link_metrics_tlvs.hpp"
58 #include "thread/link_quality.hpp"
59 
60 namespace ot {
61 class Neighbor;
62 class UnitTester;
63 
64 namespace LinkMetrics {
65 
66 /**
67  * @addtogroup core-link-metrics
68  *
69  * @brief
70  *   This module includes definitions for Thread Link Metrics query and management.
71  *
72  * @{
73  */
74 
75 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
76 
77 /**
78  * Implements the Thread Link Metrics Initiator.
79  *
80  * The Initiator makes queries, configures Link Metrics probing at the Subject and generates reports of the results.
81  */
82 class Initiator : public InstanceLocator, private NonCopyable
83 {
84 public:
85     // Initiator callbacks
86     typedef otLinkMetricsReportCallback                ReportCallback;
87     typedef otLinkMetricsMgmtResponseCallback          MgmtResponseCallback;
88     typedef otLinkMetricsEnhAckProbingIeReportCallback EnhAckProbingIeReportCallback;
89 
90     /**
91      * Provides the info used for appending MLE Link Metric Query TLV.
92      */
93     struct QueryInfo : public Clearable<QueryInfo>
94     {
95         uint8_t mSeriesId;             ///< Series ID.
96         uint8_t mTypeIds[kMaxTypeIds]; ///< Type IDs.
97         uint8_t mTypeIdCount;          ///< Number of entries in `mTypeIds[]`.
98     };
99 
100     /**
101      * Initializes an instance of the Initiator class.
102      *
103      * @param[in]  aInstance  A reference to the OpenThread interface.
104      */
105     explicit Initiator(Instance &aInstance);
106 
107     /**
108      * Sends an MLE Data Request containing Link Metrics Query TLV to query Link Metrics data.
109      *
110      * It could be either a Single Probe or a Forward Tracking Series.
111      *
112      * @param[in]  aDestination       A reference to the IPv6 address of the destination.
113      * @param[in]  aSeriesId          The Series ID to query, 0 for single probe.
114      * @param[in]  aMetrics           A pointer to metrics to query.
115      *
116      * @retval kErrorNone             Successfully sent a Link Metrics query message.
117      * @retval kErrorNoBufs           Insufficient buffers to generate the MLE Data Request message.
118      * @retval kErrorInvalidArgs      Type IDs are not valid or exceed the count limit.
119      * @retval kErrorUnknownNeighbor  @p aDestination is not link-local or the neighbor is not found.
120      */
121     Error Query(const Ip6::Address &aDestination, uint8_t aSeriesId, const Metrics *aMetrics);
122 
123     /**
124      * Appends MLE Link Metrics Query TLV to a given message.
125      *
126      * @param[in] aMessage     The message to append to.
127      * @param[in] aInfo        The link metrics query info to use to prepare the message.
128      *
129      * @retval kErrorNone     Successfully appended the TLV to the message.
130      * @retval kErrorNoBufs   Insufficient buffers available to append the TLV.
131      */
132     Error AppendLinkMetricsQueryTlv(Message &aMessage, const QueryInfo &aInfo);
133 
134     /**
135      * Registers a callback to handle Link Metrics report received.
136      *
137      * @param[in]  aCallback  A pointer to a function that is called when a Link Metrics report is received.
138      * @param[in]  aContext   A pointer to application-specific context.
139      */
SetReportCallback(ReportCallback aCallback,void * aContext)140     void SetReportCallback(ReportCallback aCallback, void *aContext) { mReportCallback.Set(aCallback, aContext); }
141 
142     /**
143      * Handles the received Link Metrics report contained in @p aMessage.
144      *
145      * @param[in]  aMessage      A reference to the message.
146      * @param[in]  aOffsetRange  The offset range in @p aMessage where the metrics report sub-TLVs are present.
147      * @param[in]  aAddress      A reference to the source address of the message.
148      */
149     void HandleReport(const Message &aMessage, OffsetRange &aOffsetRange, const Ip6::Address &aAddress);
150 
151     /**
152      * Sends an MLE Link Metrics Management Request to configure/clear a Forward Tracking Series.
153      *
154      * @param[in] aDestination       A reference to the IPv6 address of the destination.
155      * @param[in] aSeriesId          The Series ID.
156      * @param[in] aSeriesFlags       The Series Flags info which specify what types of frames are to be accounted.
157      * @param[in] aMetrics           A pointer to flags specifying what metrics to query.
158      *
159      * @retval kErrorNone             Successfully sent a Link Metrics Management Request message.
160      * @retval kErrorNoBufs           Insufficient buffers to generate the MLE Link Metrics Management Request message.
161      * @retval kErrorInvalidArgs      @p aSeriesId is not within the valid range.
162      * @retval kErrorUnknownNeighbor  @p aDestination is not link-local or the neighbor is not found.
163      */
164     Error SendMgmtRequestForwardTrackingSeries(const Ip6::Address &aDestination,
165                                                uint8_t             aSeriesId,
166                                                const SeriesFlags  &aSeriesFlags,
167                                                const Metrics      *aMetrics);
168 
169     /**
170      * Registers a callback to handle Link Metrics Management Response received.
171      *
172      * @param[in]  aCallback A pointer to a function that is called when a Link Metrics Management Response is received.
173      * @param[in]  aContext  A pointer to application-specific context.
174      */
SetMgmtResponseCallback(MgmtResponseCallback aCallback,void * aContext)175     void SetMgmtResponseCallback(MgmtResponseCallback aCallback, void *aContext)
176     {
177         mMgmtResponseCallback.Set(aCallback, aContext);
178     }
179 
180     /**
181      * Sends an MLE Link Metrics Management Request to configure/clear a Enhanced-ACK Based Probing.
182      *
183      * @param[in] aDestination       A reference to the IPv6 address of the destination.
184      * @param[in] aEnhAckFlags       Enh-ACK Flags to indicate whether to register or clear the probing. `0` to clear
185      *                               and `1` to register. Other values are reserved.
186      * @param[in] aMetrics           A pointer to flags specifying what metrics to query. Should be `nullptr` when
187      *                               `aEnhAckFlags` is `0`.
188      *
189      * @retval kErrorNone             Successfully sent a Link Metrics Management Request message.
190      * @retval kErrorNoBufs           Insufficient buffers to generate the MLE Link Metrics Management Request message.
191      * @retval kErrorInvalidArgs      @p aEnhAckFlags is not a valid value or @p aMetrics isn't correct.
192      * @retval kErrorUnknownNeighbor  @p aDestination is not link-local or the neighbor is not found.
193      */
194     Error SendMgmtRequestEnhAckProbing(const Ip6::Address &aDestination,
195                                        EnhAckFlags         aEnhAckFlags,
196                                        const Metrics      *aMetrics);
197 
198     /**
199      * Registers a callback to handle Link Metrics when Enh-ACK Probing IE is received.
200      *
201      * @param[in]  aCallback A pointer to a function that is called when Enh-ACK Probing IE is received is received.
202      * @param[in]  aContext  A pointer to application-specific context.
203      */
SetEnhAckProbingCallback(EnhAckProbingIeReportCallback aCallback,void * aContext)204     void SetEnhAckProbingCallback(EnhAckProbingIeReportCallback aCallback, void *aContext)
205     {
206         mEnhAckProbingIeReportCallback.Set(aCallback, aContext);
207     }
208 
209     /**
210      * Handles the received Link Metrics Management Response contained in @p aMessage.
211      *
212      * @param[in]  aMessage    A reference to the message that contains the Link Metrics Management Response.
213      * @param[in]  aAddress    A reference to the source address of the message.
214      *
215      * @retval kErrorNone     Successfully handled the Link Metrics Management Response.
216      * @retval kErrorParse    Cannot parse sub-TLVs from @p aMessage successfully.
217      */
218     Error HandleManagementResponse(const Message &aMessage, const Ip6::Address &aAddress);
219 
220     /**
221      * Sends an MLE Link Probe message.
222      *
223      * @param[in] aDestination    A reference to the IPv6 address of the destination.
224      * @param[in] aSeriesId       The Series ID which the Probe message targets at.
225      * @param[in] aLength         The length of the data payload in Link Probe TLV, [0, 64].
226      *
227      * @retval kErrorNone             Successfully sent a Link Probe message.
228      * @retval kErrorNoBufs           Insufficient buffers to generate the MLE Link Probe message.
229      * @retval kErrorInvalidArgs      @p aSeriesId or @p aLength is not within the valid range.
230      * @retval kErrorUnknownNeighbor  @p aDestination is not link-local or the neighbor is not found.
231      */
232     Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t aLength);
233 
234     /**
235      * Processes received Enh-ACK Probing IE data.
236      *
237      * @param[in] aData      A pointer to buffer containing the Enh-ACK Probing IE data.
238      * @param[in] aLength    The length of @p aData.
239      * @param[in] aNeighbor  The neighbor from which the Enh-ACK Probing IE was received.
240      */
241     void ProcessEnhAckIeData(const uint8_t *aData, uint8_t aLength, const Neighbor &aNeighbor);
242 
243 private:
244     static constexpr uint8_t kLinkProbeMaxLen = 64; // Max length of data payload in Link Probe TLV.
245 
246     Error FindNeighbor(const Ip6::Address &aDestination, Neighbor *&aNeighbor);
247 
248     Callback<ReportCallback>                mReportCallback;
249     Callback<MgmtResponseCallback>          mMgmtResponseCallback;
250     Callback<EnhAckProbingIeReportCallback> mEnhAckProbingIeReportCallback;
251 };
252 
253 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
254 
255 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
256 
257 /**
258  * Implements the Thread Link Metrics Subject.
259  *
260  * The Subject responds queries with reports, handles Link Metrics Management Requests and Link Probe Messages.
261  */
262 class Subject : public InstanceLocator, private NonCopyable
263 {
264 public:
265     typedef otLinkMetricsEnhAckProbingIeReportCallback EnhAckProbingIeReportCallback;
266 
267     /**
268      * Initializes an instance of the Subject class.
269      *
270      * @param[in]  aInstance  A reference to the OpenThread interface.
271      */
272     explicit Subject(Instance &aInstance);
273 
274     /**
275      * Appends a Link Metrics Report to a message according to the Link Metrics query.
276      *
277      * @param[out]  aMessage           A reference to the message to append report.
278      * @param[in]   aRequestMessage    A reference to the message of the Data Request.
279      * @param[in]   aNeighbor          A reference to the neighbor who queries the report.
280      *
281      * @retval kErrorNone         Successfully appended the Thread Discovery TLV.
282      * @retval kErrorParse        Cannot parse query sub TLV successfully.
283      * @retval kErrorInvalidArgs  QueryId is invalid or any Type ID is invalid.
284      */
285     Error AppendReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor);
286 
287     /**
288      * Handles the received Link Metrics Management Request contained in @p aMessage and return a status.
289      *
290      * @param[in]   aMessage     A reference to the message that contains the Link Metrics Management Request.
291      * @param[in]   aNeighbor    A reference to the neighbor who sends the request.
292      * @param[out]  aStatus      A reference to the status which indicates the handling result.
293      *
294      * @retval kErrorNone     Successfully handled the Link Metrics Management Request.
295      * @retval kErrorParse    Cannot parse sub-TLVs from @p aMessage successfully.
296      */
297     Error HandleManagementRequest(const Message &aMessage, Neighbor &aNeighbor, Status &aStatus);
298 
299     /**
300      * Handles the Link Probe contained in @p aMessage.
301      *
302      * @param[in]   aMessage     A reference to the message that contains the Link Probe Message.
303      * @param[out]  aSeriesId    A reference to Series ID that parsed from the message.
304      *
305      * @retval kErrorNone     Successfully handled the Link Metrics Management Response.
306      * @retval kErrorParse    Cannot parse sub-TLVs from @p aMessage successfully.
307      */
308     Error HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId);
309 
310     /**
311      * Frees a SeriesInfo entry that was allocated from the Subject object.
312      *
313      * @param[in]  aSeries    A reference to the SeriesInfo to free.
314      */
315     void Free(SeriesInfo &aSeriesInfo);
316 
317 private:
318     // Max number of SeriesInfo that could be allocated by the pool.
319 #if OPENTHREAD_FTD
320     static constexpr uint16_t kMaxSeriesSupported = OPENTHREAD_CONFIG_MLE_LINK_METRICS_MAX_SERIES_SUPPORTED;
321 #elif OPENTHREAD_MTD
322     static constexpr uint16_t kMaxSeriesSupported = OPENTHREAD_CONFIG_MLE_LINK_METRICS_SERIES_MTD;
323 #endif
324 
325     static Error ReadTypeIdsFromMessage(const Message &aMessage, const OffsetRange &aOffsetRange, Metrics &aMetrics);
326     static Error AppendReportSubTlvToMessage(Message &aMessage, const MetricsValues &aValues);
327 
328     Status ConfigureForwardTrackingSeries(uint8_t        aSeriesId,
329                                           uint8_t        aSeriesFlags,
330                                           const Metrics &aMetrics,
331                                           Neighbor      &aNeighbor);
332     Status ConfigureEnhAckProbing(uint8_t aEnhAckFlags, const Metrics &aMetrics, Neighbor &aNeighbor);
333 
334     Pool<SeriesInfo, kMaxSeriesSupported> mSeriesInfoPool;
335 };
336 
337 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
338 
339 uint8_t ScaleLinkMarginToRawValue(uint8_t aLinkMargin);
340 uint8_t ScaleRawValueToLinkMargin(uint8_t aRawValue);
341 uint8_t ScaleRssiToRawValue(int8_t aRssi);
342 int8_t  ScaleRawValueToRssi(uint8_t aRawValue);
343 
344 /**
345  * @}
346  */
347 
348 } // namespace LinkMetrics
349 } // namespace ot
350 
351 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
352 
353 #endif // LINK_METRICS_HPP
354