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