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