1 /* 2 * Copyright (c) 2020-22, 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 generating and processing Link Metrics TLVs. 32 */ 33 34 #ifndef LINK_METRICS_TYPES_HPP_ 35 #define LINK_METRICS_TYPES_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 #include <openthread/link_metrics.h> 42 43 #include "common/as_core_type.hpp" 44 #include "common/clearable.hpp" 45 #include "common/encoding.hpp" 46 #include "common/message.hpp" 47 48 namespace ot { 49 namespace LinkMetrics { 50 51 constexpr uint8_t kMaxTypeIds = 4; ///< Maximum number of Type IDs in a `Metrics`. 52 53 /** 54 * Represents Link Metric Flags indicating a set of metrics. 55 * 56 * @sa otLinkMetrics 57 */ 58 class Metrics : public otLinkMetrics, public Clearable<Metrics> 59 { 60 public: 61 /** 62 * Converts the `Metrics` into an array of Type IDs. 63 * 64 * @param[out] aTypeIds The array of Type IDs to populate. MUST have at least `kMaxTypeIds` elements. 65 * 66 * @returns Number of entries added in the array @p aTypeIds. 67 */ 68 uint8_t ConvertToTypeIds(uint8_t aTypeIds[]) const; 69 }; 70 71 /** 72 * Represents the results (values) for a set of metrics. 73 * 74 * @sa otLinkMetricsValues 75 */ 76 class MetricsValues : public otLinkMetricsValues, public Clearable<MetricsValues> 77 { 78 public: 79 /** 80 * Gets the metrics flags. 81 * 82 * @returns The metrics flags. 83 */ GetMetrics(void)84 Metrics &GetMetrics(void) { return static_cast<Metrics &>(mMetrics); } 85 86 /** 87 * Gets the metrics flags. 88 * 89 * @returns The metrics flags. 90 */ GetMetrics(void) const91 const Metrics &GetMetrics(void) const { return static_cast<const Metrics &>(mMetrics); } 92 93 /** 94 * Set the metrics flags. 95 * 96 * @param[in] aMetrics The metrics flags to set from. 97 */ SetMetrics(const Metrics & aMetrics)98 void SetMetrics(const Metrics &aMetrics) { mMetrics = aMetrics; } 99 }; 100 101 class TypeId 102 { 103 // Type ID Flags 104 // 105 // 7 6 5 4 3 2 1 0 106 // +---+---+---+---+---+---+---+---+ 107 // | E | L | Type | Metric | 108 // +---+---+---+---+---+---+---+---+ 109 // 110 111 static constexpr uint8_t kExtendedFlag = 1 << 7; 112 static constexpr uint8_t kLengthFlag = 1 << 6; 113 static constexpr uint8_t kTypeOffset = 3; 114 static constexpr uint8_t kMetricOffset = 0; 115 static constexpr uint8_t kTypeMask = (7 << kTypeOffset); 116 117 static constexpr uint8_t kTypeCount = (0 << kTypeOffset); // Count/summation 118 static constexpr uint8_t kTypeAve = (1 << kTypeOffset); // Exponential Moving average 119 static constexpr uint8_t kTypeReserved = (2 << kTypeOffset); // Reserved 120 121 static constexpr uint8_t kMetricPdu = (0 << kMetricOffset); // Number of PDUs received. 122 static constexpr uint8_t kMetricLqi = (1 << kMetricOffset); 123 static constexpr uint8_t kMetricLinkMargin = (2 << kMetricOffset); 124 static constexpr uint8_t kMetricRssi = (3 << kMetricOffset); 125 126 public: 127 static constexpr uint8_t kPdu = (kMetricPdu | kTypeCount | kLengthFlag); ///< Type ID for num PDU received. 128 static constexpr uint8_t kLqi = (kMetricLqi | kTypeAve); ///< Type ID for LQI. 129 static constexpr uint8_t kLinkMargin = (kMetricLinkMargin | kTypeAve); ///< Type ID for Link Margin. 130 static constexpr uint8_t kRssi = (kMetricRssi | kTypeAve); ///< Type ID for RSSI. 131 132 /** 133 * Indicates whether or not a given Type ID is extended. 134 * 135 * Extended Type IDs are reserved for future use. When set an additional second byte follows the current ID flags. 136 * 137 * @param[in] aTypeId The Type ID to check. 138 * 139 * @retval TRUE The @p aTypeId is extended. 140 * @retval FALSE The @p aTypeId is not extended. 141 */ IsExtended(uint8_t aTypeId)142 static bool IsExtended(uint8_t aTypeId) { return (aTypeId & kExtendedFlag); } 143 144 /** 145 * Determines the value length (number of bytes) associated with a given Type ID. 146 * 147 * Type IDs can either have a short value as a `uint8_t` (e.g., `kLqi`, `kLinkMargin` or `kRssi`) or a long value as 148 * a `uint32_t` (`kPdu`). 149 * 150 * @param[in] aTypeId The Type ID. 151 * 152 * @returns the associated value length of @p aTypeId. 153 */ GetValueLength(uint8_t aTypeId)154 static uint8_t GetValueLength(uint8_t aTypeId) 155 { 156 return (aTypeId & kLengthFlag) ? sizeof(uint32_t) : sizeof(uint8_t); 157 } 158 159 /** 160 * Updates a Type ID to mark it as reversed. 161 * 162 * This is used for testing only. 163 * 164 * @param[in, out] aTypeId A reference to a Type ID variable to update. 165 */ MarkAsReserved(uint8_t & aTypeId)166 static void MarkAsReserved(uint8_t &aTypeId) { aTypeId = (aTypeId & ~kTypeMask) | kTypeReserved; } 167 168 TypeId(void) = delete; 169 }; 170 171 /** 172 * Represents the Series Flags for Forward Tracking Series. 173 */ 174 class SeriesFlags : public otLinkMetricsSeriesFlags 175 { 176 public: 177 /** 178 * Converts the `SeriesFlags` to `uint8_t` bit-mask (for inclusion in TLVs). 179 * 180 * @returns The bit-mask representation. 181 */ 182 uint8_t ConvertToMask(void) const; 183 184 /** 185 * Sets the `SeriesFlags` from a given bit-mask value. 186 * 187 * @param[in] aFlagsMask The bit-mask flags. 188 */ 189 void SetFrom(uint8_t aFlagsMask); 190 191 /** 192 * Indicates whether or not the Link Probe flag is set. 193 * 194 * @retval true The Link Probe flag is set. 195 * @retval false The Link Probe flag is not set. 196 */ IsLinkProbeFlagSet(void) const197 bool IsLinkProbeFlagSet(void) const { return mLinkProbe; } 198 199 /** 200 * Indicates whether or not the MAC Data flag is set. 201 * 202 * @retval true The MAC Data flag is set. 203 * @retval false The MAC Data flag is not set. 204 */ IsMacDataFlagSet(void) const205 bool IsMacDataFlagSet(void) const { return mMacData; } 206 207 /** 208 * Indicates whether or not the MAC Data Request flag is set. 209 * 210 * @retval true The MAC Data Request flag is set. 211 * @retval false The MAC Data Request flag is not set. 212 */ IsMacDataRequestFlagSet(void) const213 bool IsMacDataRequestFlagSet(void) const { return mMacDataRequest; } 214 215 /** 216 * Indicates whether or not the Mac Ack flag is set. 217 * 218 * @retval true The Mac Ack flag is set. 219 * @retval false The Mac Ack flag is not set. 220 */ IsMacAckFlagSet(void) const221 bool IsMacAckFlagSet(void) const { return mMacAck; } 222 223 private: 224 static constexpr uint8_t kLinkProbeFlag = 1 << 0; 225 static constexpr uint8_t kMacDataFlag = 1 << 1; 226 static constexpr uint8_t kMacDataRequestFlag = 1 << 2; 227 static constexpr uint8_t kMacAckFlag = 1 << 3; 228 }; 229 230 /** 231 * Type represent Enhanced-ACK Flags. 232 */ 233 enum EnhAckFlags : uint8_t 234 { 235 kEnhAckClear = OT_LINK_METRICS_ENH_ACK_CLEAR, ///< Clear. 236 kEnhAckRegister = OT_LINK_METRICS_ENH_ACK_REGISTER, ///< Register. 237 }; 238 239 /** 240 * Represents one Series that is being tracked by the Subject. 241 * 242 * When an Initiator successfully configured a Forward Tracking Series, the Subject would use an instance of this class 243 * to track the information of the Series. The Subject has a `Pool` of `SeriesInfo`. It would allocate one when a new 244 * Series comes, and free it when a Series finishes. 245 * 246 * Inherits `LinkedListEntry` and each `Neighbor` has a list of `SeriesInfo` so that the Subject could track 247 * per Series initiated by neighbors as long as it has available resources. 248 */ 249 class SeriesInfo : public LinkedListEntry<SeriesInfo> 250 { 251 friend class LinkedList<SeriesInfo>; 252 friend class LinkedListEntry<SeriesInfo>; 253 254 public: 255 /** 256 * This constant represents Link Probe when filtering frames to be accounted using Series Flag. There's 257 * already `Mac::Frame::kTypeData`, `Mac::Frame::kTypeAck` and `Mac::Frame::kTypeMacCmd`. This item is 258 * added so that we can filter a Link Probe for series in the same way as other frames. 259 */ 260 static constexpr uint8_t kSeriesTypeLinkProbe = 0; 261 262 /** 263 * Initializes the SeriesInfo object. 264 * 265 * @param[in] aSeriesId The Series ID. 266 * @param[in] aSeriesFlagsMask The Series Flags bitmask which specify what types of frames are to be accounted. 267 * @param[in] aMetrics Metrics to query. 268 */ 269 void Init(uint8_t aSeriesId, uint8_t aSeriesFlagsMask, const Metrics &aMetrics); 270 271 /** 272 * Gets the Series ID. 273 * 274 * @returns The Series ID. 275 */ GetSeriesId(void) const276 uint8_t GetSeriesId(void) const { return mSeriesId; } 277 278 /** 279 * Gets the PDU count. 280 * 281 * @returns The PDU count. 282 */ GetPduCount(void) const283 uint32_t GetPduCount(void) const { return mPduCount; } 284 285 /** 286 * Gets the average LQI. 287 * 288 * @returns The average LQI. 289 */ GetAverageLqi(void) const290 uint8_t GetAverageLqi(void) const { return mLqiAverager.GetAverage(); } 291 292 /** 293 * Gets the average RSS. 294 * 295 * @returns The average RSS. 296 */ GetAverageRss(void) const297 int8_t GetAverageRss(void) const { return mRssAverager.GetAverage(); } 298 299 /** 300 * Aggregates the Link Metrics data of a frame into this series. 301 * 302 * @param[in] aFrameType The type of the frame. 303 * @param[in] aLqi The LQI value. 304 * @param[in] aRss The RSS value. 305 */ 306 void AggregateLinkMetrics(uint8_t aFrameType, uint8_t aLqi, int8_t aRss); 307 308 /** 309 * Gets the metrics. 310 * 311 * @returns The metrics associated with `SeriesInfo`. 312 */ GetLinkMetrics(void) const313 const Metrics &GetLinkMetrics(void) const { return mMetrics; } 314 315 private: Matches(const uint8_t & aSeriesId) const316 bool Matches(const uint8_t &aSeriesId) const { return mSeriesId == aSeriesId; } 317 bool IsFrameTypeMatch(uint8_t aFrameType) const; 318 319 SeriesInfo *mNext; 320 uint8_t mSeriesId; 321 SeriesFlags mSeriesFlags; 322 Metrics mMetrics; 323 RssAverager mRssAverager; 324 LqiAverager mLqiAverager; 325 uint32_t mPduCount; 326 }; 327 328 /** 329 * Type represents Link Metrics Status. 330 */ 331 enum Status : uint8_t 332 { 333 kStatusSuccess = OT_LINK_METRICS_STATUS_SUCCESS, 334 kStatusCannotSupportNewSeries = OT_LINK_METRICS_STATUS_CANNOT_SUPPORT_NEW_SERIES, 335 kStatusSeriesIdAlreadyRegistered = OT_LINK_METRICS_STATUS_SERIESID_ALREADY_REGISTERED, 336 kStatusSeriesIdNotRecognized = OT_LINK_METRICS_STATUS_SERIESID_NOT_RECOGNIZED, 337 kStatusNoMatchingFramesReceived = OT_LINK_METRICS_STATUS_NO_MATCHING_FRAMES_RECEIVED, 338 kStatusOtherError = OT_LINK_METRICS_STATUS_OTHER_ERROR, 339 }; 340 341 } // namespace LinkMetrics 342 343 DefineCoreType(otLinkMetrics, LinkMetrics::Metrics); 344 DefineCoreType(otLinkMetricsValues, LinkMetrics::MetricsValues); 345 DefineCoreType(otLinkMetricsSeriesFlags, LinkMetrics::SeriesFlags); 346 DefineMapEnum(otLinkMetricsEnhAckFlags, LinkMetrics::EnhAckFlags); 347 DefineMapEnum(otLinkMetricsStatus, LinkMetrics::Status); 348 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_TYPES_HPP_ 354