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