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] aOffset The offset in bytes where the metrics report sub-TLVs start. 152 * @param[in] aLength The length of the metrics report sub-TLVs in bytes. 153 * @param[in] aAddress A reference to the source address of the message. 154 * 155 */ 156 void HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t aLength, const Ip6::Address &aAddress); 157 158 /** 159 * Sends an MLE Link Metrics Management Request to configure/clear a Forward Tracking Series. 160 * 161 * @param[in] aDestination A reference to the IPv6 address of the destination. 162 * @param[in] aSeriesId The Series ID. 163 * @param[in] aSeriesFlags The Series Flags info which specify what types of frames are to be accounted. 164 * @param[in] aMetrics A pointer to flags specifying what metrics to query. 165 * 166 * @retval kErrorNone Successfully sent a Link Metrics Management Request message. 167 * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Metrics Management Request message. 168 * @retval kErrorInvalidArgs @p aSeriesId is not within the valid range. 169 * @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found. 170 * 171 */ 172 Error SendMgmtRequestForwardTrackingSeries(const Ip6::Address &aDestination, 173 uint8_t aSeriesId, 174 const SeriesFlags &aSeriesFlags, 175 const Metrics *aMetrics); 176 177 /** 178 * Registers a callback to handle Link Metrics Management Response received. 179 * 180 * @param[in] aCallback A pointer to a function that is called when a Link Metrics Management Response is received. 181 * @param[in] aContext A pointer to application-specific context. 182 * 183 */ SetMgmtResponseCallback(MgmtResponseCallback aCallback,void * aContext)184 void SetMgmtResponseCallback(MgmtResponseCallback aCallback, void *aContext) 185 { 186 mMgmtResponseCallback.Set(aCallback, aContext); 187 } 188 189 /** 190 * Sends an MLE Link Metrics Management Request to configure/clear a Enhanced-ACK Based Probing. 191 * 192 * @param[in] aDestination A reference to the IPv6 address of the destination. 193 * @param[in] aEnhAckFlags Enh-ACK Flags to indicate whether to register or clear the probing. `0` to clear 194 * and `1` to register. Other values are reserved. 195 * @param[in] aMetrics A pointer to flags specifying what metrics to query. Should be `nullptr` when 196 * `aEnhAckFlags` is `0`. 197 * 198 * @retval kErrorNone Successfully sent a Link Metrics Management Request message. 199 * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Metrics Management Request message. 200 * @retval kErrorInvalidArgs @p aEnhAckFlags is not a valid value or @p aMetrics isn't correct. 201 * @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found. 202 * 203 */ 204 Error SendMgmtRequestEnhAckProbing(const Ip6::Address &aDestination, 205 EnhAckFlags aEnhAckFlags, 206 const Metrics *aMetrics); 207 208 /** 209 * Registers a callback to handle Link Metrics when Enh-ACK Probing IE is received. 210 * 211 * @param[in] aCallback A pointer to a function that is called when Enh-ACK Probing IE is received is received. 212 * @param[in] aContext A pointer to application-specific context. 213 * 214 */ SetEnhAckProbingCallback(EnhAckProbingIeReportCallback aCallback,void * aContext)215 void SetEnhAckProbingCallback(EnhAckProbingIeReportCallback aCallback, void *aContext) 216 { 217 mEnhAckProbingIeReportCallback.Set(aCallback, aContext); 218 } 219 220 /** 221 * Handles the received Link Metrics Management Response contained in @p aMessage. 222 * 223 * @param[in] aMessage A reference to the message that contains the Link Metrics Management Response. 224 * @param[in] aAddress A reference to the source address of the message. 225 * 226 * @retval kErrorNone Successfully handled the Link Metrics Management Response. 227 * @retval kErrorParse Cannot parse sub-TLVs from @p aMessage successfully. 228 * 229 */ 230 Error HandleManagementResponse(const Message &aMessage, const Ip6::Address &aAddress); 231 232 /** 233 * Sends an MLE Link Probe message. 234 * 235 * @param[in] aDestination A reference to the IPv6 address of the destination. 236 * @param[in] aSeriesId The Series ID which the Probe message targets at. 237 * @param[in] aLength The length of the data payload in Link Probe TLV, [0, 64]. 238 * 239 * @retval kErrorNone Successfully sent a Link Probe message. 240 * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Probe message. 241 * @retval kErrorInvalidArgs @p aSeriesId or @p aLength is not within the valid range. 242 * @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found. 243 * 244 */ 245 Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t aLength); 246 247 /** 248 * Processes received Enh-ACK Probing IE data. 249 * 250 * @param[in] aData A pointer to buffer containing the Enh-ACK Probing IE data. 251 * @param[in] aLength The length of @p aData. 252 * @param[in] aNeighbor The neighbor from which the Enh-ACK Probing IE was received. 253 * 254 */ 255 void ProcessEnhAckIeData(const uint8_t *aData, uint8_t aLength, const Neighbor &aNeighbor); 256 257 private: 258 static constexpr uint8_t kLinkProbeMaxLen = 64; // Max length of data payload in Link Probe TLV. 259 260 Error FindNeighbor(const Ip6::Address &aDestination, Neighbor *&aNeighbor); 261 262 Callback<ReportCallback> mReportCallback; 263 Callback<MgmtResponseCallback> mMgmtResponseCallback; 264 Callback<EnhAckProbingIeReportCallback> mEnhAckProbingIeReportCallback; 265 }; 266 267 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 268 269 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 270 271 /** 272 * Implements the Thread Link Metrics Subject. 273 * 274 * The Subject reponds queries with reports, handles Link Metrics Management Requests and Link Probe Messages. 275 * 276 */ 277 class Subject : public InstanceLocator, private NonCopyable 278 { 279 public: 280 typedef otLinkMetricsEnhAckProbingIeReportCallback EnhAckProbingIeReportCallback; 281 282 /** 283 * Initializes an instance of the Subject class. 284 * 285 * @param[in] aInstance A reference to the OpenThread interface. 286 * 287 */ 288 explicit Subject(Instance &aInstance); 289 290 /** 291 * Appends a Link Metrics Report to a message according to the Link Metrics query. 292 * 293 * @param[out] aMessage A reference to the message to append report. 294 * @param[in] aRequestMessage A reference to the message of the Data Request. 295 * @param[in] aNeighbor A reference to the neighbor who queries the report. 296 * 297 * @retval kErrorNone Successfully appended the Thread Discovery TLV. 298 * @retval kErrorParse Cannot parse query sub TLV successfully. 299 * @retval kErrorInvalidArgs QueryId is invalid or any Type ID is invalid. 300 * 301 */ 302 Error AppendReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor); 303 304 /** 305 * Handles the received Link Metrics Management Request contained in @p aMessage and return a status. 306 * 307 * @param[in] aMessage A reference to the message that contains the Link Metrics Management Request. 308 * @param[in] aNeighbor A reference to the neighbor who sends the request. 309 * @param[out] aStatus A reference to the status which indicates the handling result. 310 * 311 * @retval kErrorNone Successfully handled the Link Metrics Management Request. 312 * @retval kErrorParse Cannot parse sub-TLVs from @p aMessage successfully. 313 * 314 */ 315 Error HandleManagementRequest(const Message &aMessage, Neighbor &aNeighbor, Status &aStatus); 316 317 /** 318 * Handles the Link Probe contained in @p aMessage. 319 * 320 * @param[in] aMessage A reference to the message that contains the Link Probe Message. 321 * @param[out] aSeriesId A reference to Series ID that parsed from the message. 322 * 323 * @retval kErrorNone Successfully handled the Link Metrics Management Response. 324 * @retval kErrorParse Cannot parse sub-TLVs from @p aMessage successfully. 325 * 326 */ 327 Error HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId); 328 329 /** 330 * Frees a SeriesInfo entry that was allocated from the Subject object. 331 * 332 * @param[in] aSeries A reference to the SeriesInfo to free. 333 * 334 */ 335 void Free(SeriesInfo &aSeriesInfo); 336 337 private: 338 // Max number of SeriesInfo that could be allocated by the pool. 339 #if OPENTHREAD_FTD 340 static constexpr uint16_t kMaxSeriesSupported = OPENTHREAD_CONFIG_MLE_LINK_METRICS_MAX_SERIES_SUPPORTED; 341 #elif OPENTHREAD_MTD 342 static constexpr uint16_t kMaxSeriesSupported = OPENTHREAD_CONFIG_MLE_LINK_METRICS_SERIES_MTD; 343 #endif 344 345 static Error ReadTypeIdsFromMessage(const Message &aMessage, 346 uint16_t aStartOffset, 347 uint16_t aEndOffset, 348 Metrics &aMetrics); 349 static Error AppendReportSubTlvToMessage(Message &aMessage, const MetricsValues &aValues); 350 351 Status ConfigureForwardTrackingSeries(uint8_t aSeriesId, 352 uint8_t aSeriesFlags, 353 const Metrics &aMetrics, 354 Neighbor &aNeighbor); 355 Status ConfigureEnhAckProbing(uint8_t aEnhAckFlags, const Metrics &aMetrics, Neighbor &aNeighbor); 356 357 Pool<SeriesInfo, kMaxSeriesSupported> mSeriesInfoPool; 358 }; 359 360 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 361 362 uint8_t ScaleLinkMarginToRawValue(uint8_t aLinkMargin); 363 uint8_t ScaleRawValueToLinkMargin(uint8_t aRawValue); 364 uint8_t ScaleRssiToRawValue(int8_t aRssi); 365 int8_t ScaleRawValueToRssi(uint8_t aRawValue); 366 367 /** 368 * @} 369 */ 370 371 } // namespace LinkMetrics 372 } // namespace ot 373 374 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 375 376 #endif // LINK_METRICS_HPP 377