• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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