blob: 7cb939508b527b5238fd314da34366869049d8b0 [file] [log] [blame]
Abtin Keshavarziancb338982016-06-27 14:15:11 -07001/*
Jonathan Hui44350172016-09-13 15:57:11 -07002 * Copyright (c) 2016, The OpenThread Authors.
Abtin Keshavarziancb338982016-06-27 14:15:11 -07003 * 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 storing and processing link quality information.
32 */
33
34#ifndef LINK_QUALITY_HPP_
35#define LINK_QUALITY_HPP_
36
Abtin Keshavarzian2ea56442017-10-17 09:46:34 -070037#include "openthread-core-config.h"
38
Jonathan Hui69d98d42018-02-06 14:14:57 -080039#include <openthread/platform/radio.h>
Abtin Keshavarziancb338982016-06-27 14:15:11 -070040
Abtin Keshavarzian4b918f82018-06-11 09:10:52 -070041#include "common/string.hpp"
42
Jonathan Hui1eabda62017-04-27 22:29:05 -070043namespace ot {
Abtin Keshavarziancb338982016-06-27 14:15:11 -070044
45/**
46 * @addtogroup core-link-quality
47 *
48 * @brief
49 * This module includes definitions for Thread link quality metrics.
50 *
51 * @{
52 */
53
Abtin Keshavarzianc2d22742018-01-22 08:56:18 -080054/**
55 * This class implements an operation Success Rate Tracker.
56 *
57 * This can be used to track different link quality related metrics, e.g., CCA failure rate, frame tx success rate).
58 * The success rate is maintained using an exponential moving IIR averaging filter with a `uint16_t` as the storage.
59 *
60 */
61class SuccessRateTracker
62{
63public:
64 enum
65 {
Jonathan Hui69d98d42018-02-06 14:14:57 -080066 kMaxRateValue = 0xffff, ///< Indicates value corresponding to maximum (failure/success) rate of 100%.
Abtin Keshavarzianc2d22742018-01-22 08:56:18 -080067 };
68
69 /**
Abtin Keshavarzianc2d22742018-01-22 08:56:18 -080070 * This method resets the tracker to its initialized state, setting success rate to 100%.
71 *
72 */
Abtin Keshavarzian68a605f2018-01-31 12:40:23 -080073 void Reset(void) { mFailureRate = 0; }
Abtin Keshavarzianc2d22742018-01-22 08:56:18 -080074
75 /**
76 * This method adds a sample (success or failure) to `SuccessRateTracker`.
77 *
78 * @param[in] aSuccess The sample status be added, `true` for success, `false` for failure.
79 * @param[in] aWeight The weight coefficient used for adding the new sample into average.
80 *
81 */
82 void AddSample(bool aSuccess, uint16_t aWeight = kDefaultWeight);
83
84 /**
85 * This method returns the average failure rate.
86 *
87 * @retval the average failure rate `[0-kMaxRateValue]` with `kMaxRateValue` corresponding to 100%.
88 *
89 */
Abtin Keshavarzian68a605f2018-01-31 12:40:23 -080090 uint16_t GetFailureRate(void) const { return mFailureRate; }
Abtin Keshavarzianc2d22742018-01-22 08:56:18 -080091
92 /**
93 * This method returns the average success rate.
94 *
95 * @retval the average success rate as [0-kMaxRateValue] with `kMaxRateValue` corresponding to 100%.
96 *
97 */
Abtin Keshavarzian68a605f2018-01-31 12:40:23 -080098 uint16_t GetSuccessRate(void) const { return kMaxRateValue - mFailureRate; }
Abtin Keshavarzianc2d22742018-01-22 08:56:18 -080099
100private:
101 enum
102 {
103 kDefaultWeight = 64,
104 };
105
Abtin Keshavarzian68a605f2018-01-31 12:40:23 -0800106 uint16_t mFailureRate;
Abtin Keshavarzianc2d22742018-01-22 08:56:18 -0800107};
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700108
109/**
110 * This class implements a Received Signal Strength (RSS) averager.
111 *
112 * The average is maintained using an adaptive exponentially weighted moving filter.
113 *
114 */
115class RssAverager
116{
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700117public:
118 enum
119 {
Jonathan Hui69d98d42018-02-06 14:14:57 -0800120 kStringSize = 10, ///< Max chars needed for a string representation of average (@sa ToString()).
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700121 };
122
123 /**
Abtin Keshavarzian4b918f82018-06-11 09:10:52 -0700124 * This type defines the fixed-length `String` object returned from `ToString()`.
125 *
126 */
127 typedef String<kStringSize> InfoString;
128
129 /**
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700130 * This method reset the averager and clears the average value.
131 *
132 */
133 void Reset(void);
134
135 /**
136 * This method indicates whether the averager contains an average (i.e., at least one RSS value has been added).
137 *
138 * @retval true If the average value is available (at least one RSS value has been added).
139 * @retval false Averager is empty (no RSS value added yet).
140 *
141 */
142 bool HasAverage(void) const { return (mCount != 0); }
143
144 /**
145 * This method adds a received signal strength (RSS) value to the average.
146 *
147 * If @p aRss is OT_RADIO_RSSI_INVALID, it is ignored and error status OT_ERROR_INVALID_ARGS is returned.
148 * The value of RSS is capped at 0dBm (i.e., for any given RSS value higher than 0dBm, 0dBm is used instead).
149 *
150 * @param[in] aRss Received signal strength value (in dBm) to be added to the average.
151 *
152 * @retval OT_ERROR_NONE New RSS value added to average successfully.
153 * @retval OT_ERROR_INVALID_ARGS Value of @p aRss is OT_RADIO_RSSI_INVALID.
154 *
155 */
156 otError Add(int8_t aRss);
157
158 /**
159 * This method returns the current average signal strength value maintained by the averager.
160 *
161 * @returns The current average value (in dBm) or OT_RADIO_RSSI_INVALID if no average is available.
162 *
163 */
164 int8_t GetAverage(void) const;
165
166 /**
167 * This method returns an raw/encoded version of current average signal strength value. The raw value is the
168 * average multiplied by a precision factor (currently set as -8).
169 *
170 * @returns The current average multiplied by precision factor or zero if no average is available.
171 *
172 */
173 uint16_t GetRaw(void) const { return mAverage; }
174
175 /**
176 * This method converts the current average RSS value to a human-readable string (e.g., "-80.375"). If the
177 * average is unknown, empty string is returned.
178 *
Abtin Keshavarzian4b918f82018-06-11 09:10:52 -0700179 * @returns An `InfoString` object containing the string representation of average RSS.
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700180 *
181 */
Abtin Keshavarzian4b918f82018-06-11 09:10:52 -0700182 InfoString ToString(void) const;
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700183
184private:
185 /*
186 * The RssAverager uses an adaptive exponentially weighted filter to maintain the average. It keeps track of
187 * current average and the number of added RSS values (up to a 8).
188 *
189 * For the first 8 added RSS values, the average is the arithmetic mean of the added values (e.g., if 5 values are
190 * added, the average is sum of the 5 added RSS values divided by 5. After the 8th RSS value, a weighted filter is
191 * used with coefficients (1/8, 7/8), i.e., newAverage = 1/8 * newRss + 7/8 * oldAverage.
192 *
193 * To add to accuracy of the averaging process, the RSS values and the maintained average are multiplied by a
194 * precision factor of -8.
195 *
196 */
197
198 enum
199 {
Jonathan Hui69d98d42018-02-06 14:14:57 -0800200 kPrecisionBitShift = 3, // Precision multiple for RSS average (1 << PrecisionBitShift).
201 kPrecision = (1 << kPrecisionBitShift),
202 kPrecisionBitMask = (kPrecision - 1),
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700203
Jonathan Hui69d98d42018-02-06 14:14:57 -0800204 kCoeffBitShift = 3, // Coefficient used for exponentially weighted filter (1 << kCoeffBitShift).
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700205 };
206
207 // Member variables fit into two bytes.
208
Jonathan Hui69d98d42018-02-06 14:14:57 -0800209 uint16_t mAverage : 11; // The raw average signal strength value (stored as RSS times precision multiple).
210 uint16_t mCount : 5; // Number of RSS values added to averager so far (limited to 2^kCoeffBitShift-1).
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700211};
212
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700213/**
214 * This class encapsulates/stores all relevant information about quality of a link, including average received signal
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700215 * strength (RSS), last RSS, link margin, and link quality.
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700216 *
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700217 */
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700218class LinkQualityInfo
219{
220public:
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700221 enum
222 {
Jonathan Hui69d98d42018-02-06 14:14:57 -0800223 kInfoStringSize = 50, ///< Max chars needed for the info string representation (@sa ToInfoString())
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700224 };
225
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700226 /**
Abtin Keshavarzian4b918f82018-06-11 09:10:52 -0700227 * This type defines the fixed-length `String` object returned from `ToInfoString()`.
228 *
229 */
230 typedef String<kInfoStringSize> InfoString;
231
232 /**
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700233 * This method clears the all the data in the object.
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700234 *
235 */
236 void Clear(void);
237
238 /**
239 * This method adds a new received signal strength (RSS) value to the average.
240 *
Shu Chen66f6e702017-05-05 11:38:37 +0800241 * @param[in] aNoiseFloor The noise floor value (in dBm).
Abtin Keshavarzianb3976f52017-04-14 14:32:55 -0700242 * @param[in] aRss A new received signal strength value (in dBm) to be added to the average.
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700243 *
244 */
Shu Chen66f6e702017-05-05 11:38:37 +0800245 void AddRss(int8_t aNoiseFloor, int8_t aRss);
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700246
247 /**
Abtin Keshavarzianc2d22742018-01-22 08:56:18 -0800248 * This method returns the current average received signal strength value.
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700249 *
Shu Chen6e3d6632017-06-13 02:05:40 +0800250 * @returns The current average value or @c OT_RADIO_RSSI_INVALID if no average is available.
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700251 *
252 */
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700253 int8_t GetAverageRss(void) const { return mRssAverager.GetAverage(); }
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700254
255 /**
256 * This method returns an encoded version of current average signal strength value. The encoded value is the
257 * average multiplied by a precision factor (currently -8).
258 *
259 * @returns The current average multiplied by precision factor or zero if no average is available.
260 *
261 */
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700262 uint16_t GetAverageRssRaw(void) const { return mRssAverager.GetRaw(); }
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700263
264 /**
Abtin Keshavarzian4b918f82018-06-11 09:10:52 -0700265 * This method converts the link quality info to info/debug human-readable string.
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700266 *
Abtin Keshavarzian4b918f82018-06-11 09:10:52 -0700267 * @returns An `InfoString` representing the link quality info.
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700268 *
269 */
Abtin Keshavarzian4b918f82018-06-11 09:10:52 -0700270 InfoString ToInfoString(void) const;
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700271
272 /**
273 * This method returns the link margin. The link margin is calculated using the link's current average received
274 * signal strength (RSS) and average noise floor.
275 *
Shu Chen66f6e702017-05-05 11:38:37 +0800276 * @param[in] aNoiseFloor The noise floor value (in dBm).
Jonathan Hui28a56452016-08-29 21:49:50 -0700277 *
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700278 * @returns Link margin derived from average received signal strength and average noise floor.
279 *
280 */
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700281 uint8_t GetLinkMargin(int8_t aNoiseFloor) const { return ConvertRssToLinkMargin(aNoiseFloor, GetAverageRss()); }
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700282
283 /**
284 * Returns the current one-way link quality value. The link quality value is a number 0-3.
285 *
286 * The link quality is calculated by comparing the current link margin with a set of thresholds (per Thread spec).
287 * More specifically, link margin > 20 dB gives link quality 3, link margin > 10 dB gives link quality 2,
288 * link margin > 2 dB gives link quality 1, and link margin below or equal to 2 dB yields link quality of 0.
289 *
290 * In order to ensure that a link margin near the boundary of two different link quality values does not cause
291 * frequent changes, a hysteresis of 2 dB is applied when determining the link quality. For example, the average
292 * link margin must be at least 12 dB to change a quality 1 link to a quality 2 link.
293 *
Shu Chen66f6e702017-05-05 11:38:37 +0800294 * @param[in] aNoiseFloor The noise floor value (in dBm).
Jonathan Hui28a56452016-08-29 21:49:50 -0700295 *
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700296 * @returns The current link quality value (value 0-3 as per Thread specification).
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700297 *
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700298 */
Abtin Keshavarzian68a605f2018-01-31 12:40:23 -0800299 uint8_t GetLinkQuality(void) const { return mLinkQuality; }
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700300
301 /**
Adam Eliot89521042017-03-28 09:41:57 -0700302 * Returns the most recent RSS value.
303 *
304 * @returns The most recent RSS
305 *
306 */
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700307 int8_t GetLastRss(void) const { return mLastRss; }
Adam Eliot89521042017-03-28 09:41:57 -0700308
Abtin Keshavarzian68a605f2018-01-31 12:40:23 -0800309 /**
310 * This method adds a MAC frame transmission status (success/failure) and updates the frame tx error rate.
311 *
312 * @param[in] aTxStatus Success/Failure of MAC frame transmission (`true` -> success, `false` -> failure).
313 *
314 */
Jonathan Hui69d98d42018-02-06 14:14:57 -0800315 void AddFrameTxStatus(bool aTxStatus)
316 {
Abtin Keshavarzian68a605f2018-01-31 12:40:23 -0800317 mFrameErrorRate.AddSample(aTxStatus, OPENTHREAD_CONFIG_FRAME_TX_ERR_RATE_AVERAGING_WINDOW);
318 }
319
320 /**
321 * This method adds a message transmission status (success/failure) and updates the message error rate.
322 *
323 * @param[in] aTxStatus Success/Failure of message (`true` -> success, `false` -> message tx failed).
324 * A larger (IPv6) message may be fragmented and sent as multiple MAC frames. The message
325 * transmission is considered a failure, if any of its fragments fail after all MAC retry
326 * attempts.
327 *
328 */
Jonathan Hui69d98d42018-02-06 14:14:57 -0800329 void AddMessageTxStatus(bool aTxStatus)
330 {
Abtin Keshavarzian68a605f2018-01-31 12:40:23 -0800331 mMessageErrorRate.AddSample(aTxStatus, OPENTHREAD_CONFIG_IPV6_TX_ERR_RATE_AVERAGING_WINDOW);
332 }
333
334 /**
335 * This method returns the MAC frame transmission error rate for the link.
336 *
337 * The rate is maintained over a window of (roughly) last `OPENTHREAD_CONFIG_FRAME_TX_ERR_RATE_AVERAGING_WINDOW`
338 * frame transmissions.
339 *
340 * @returns The error rate with maximum value `0xffff` corresponding to 100% failure rate.
341 *
342 */
343 uint16_t GetFrameErrorRate(void) const { return mFrameErrorRate.GetFailureRate(); }
344
345 /**
346 * This method returns the message error rate for the link.
347 *
348 * The rate is maintained over a window of (roughly) last `OPENTHREAD_CONFIG_IPV6_TX_ERR_RATE_AVERAGING_WINDOW`
349 * (IPv6) messages.
350 *
351 * Note that a larger (IPv6) message can be fragmented and sent as multiple MAC frames. The message transmission is
352 * considered a failure, if any of its fragments fail after all MAC retry attempts.
353 *
354 * @returns The error rate with maximum value `0xffff` corresponding to 100% failure rate.
355 *
356 */
357 uint16_t GetMessageErrorRate(void) const { return mMessageErrorRate.GetFailureRate(); }
358
Adam Eliot89521042017-03-28 09:41:57 -0700359 /**
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700360 * This method converts a received signal strength value to a link margin value.
361 *
Shu Chen66f6e702017-05-05 11:38:37 +0800362 * @param[in] aNoiseFloor The noise floor value (in dBm).
Abtin Keshavarzianb3976f52017-04-14 14:32:55 -0700363 * @param[in] aRss The received signal strength value (in dBm).
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700364 *
365 * @returns The link margin value.
366 *
367 */
Shu Chen66f6e702017-05-05 11:38:37 +0800368 static uint8_t ConvertRssToLinkMargin(int8_t aNoiseFloor, int8_t aRss);
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700369
370 /**
371 * This method converts a link margin value to a link quality value.
372 *
373 * @param[in] aLinkMargin The Link Margin in dB.
374 *
375 * @returns The link quality value (0-3).
376 *
377 */
378 static uint8_t ConvertLinkMarginToLinkQuality(uint8_t aLinkMargin);
379
380 /**
381 * This method converts a received signal strength value to a link quality value.
382 *
Shu Chen66f6e702017-05-05 11:38:37 +0800383 * @param[in] aNoiseFloor The noise floor value (in dBm).
Abtin Keshavarzianb3976f52017-04-14 14:32:55 -0700384 * @param[in] aRss The received signal strength value (in dBm).
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700385 *
386 * @returns The link quality value (0-3).
387 *
388 */
Shu Chen66f6e702017-05-05 11:38:37 +0800389 static uint8_t ConvertRssToLinkQuality(int8_t aNoiseFloor, int8_t aRss);
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700390
rongli502c6ca2017-07-12 13:38:49 +0800391 /**
392 * This method converts a link quality value to a typical received signal strength value .
393 * @note only for test
394 *
395 * @param[in] aNoiseFloor The noise floor value (in dBm).
396 * @param[in] aLinkQuality The link quality value in [0, 3].
397 *
398 * @returns The typical platform rssi.
399 *
400 */
401 static int8_t ConvertLinkQualityToRss(int8_t aNoiseFloor, uint8_t aLinkQuality);
402
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700403private:
404 enum
405 {
406 // Constants for obtaining link quality from link margin:
407
Jonathan Hui69d98d42018-02-06 14:14:57 -0800408 kThreshold3 = 20, ///< Link margin threshold for quality 3 link.
409 kThreshold2 = 10, ///< Link margin threshold for quality 2 link.
410 kThreshold1 = 2, ///< Link margin threshold for quality 1 link.
411 kHysteresisThreshold = 2, ///< Link margin hysteresis threshold.
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700412
rongli502c6ca2017-07-12 13:38:49 +0800413 // constants for test:
414
Jonathan Hui69d98d42018-02-06 14:14:57 -0800415 kLinkQuality3LinkMargin = 50, ///< link margin for Link Quality 3 (21 - 255)
416 kLinkQuality2LinkMargin = 15, ///< link margin for Link Quality 3 (21 - 255)
417 kLinkQuality1LinkMargin = 5, ///< link margin for Link Quality 3 (21 - 255)
418 kLinkQuality0LinkMargin = 0, ///< link margin for Link Quality 3 (21 - 255)
rongli502c6ca2017-07-12 13:38:49 +0800419
Jonathan Hui69d98d42018-02-06 14:14:57 -0800420 kNoLinkQuality = 0xff, // Used to indicate that there is no previous/last link quality.
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700421 };
422
Abtin Keshavarzian68a605f2018-01-31 12:40:23 -0800423 void SetLinkQuality(uint8_t aLinkQuality) { mLinkQuality = aLinkQuality; }
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700424
425 /* Static private method to calculate the link quality from a given link margin while taking into account the last
426 * link quality value and adding the hysteresis value to the thresholds. If there is no previous value for link
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700427 * quality, the constant kNoLinkQuality should be passed as the second argument.
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700428 *
429 */
430 static uint8_t CalculateLinkQuality(uint8_t aLinkMargin, uint8_t aLastLinkQuality);
431
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700432 RssAverager mRssAverager;
Abtin Keshavarzian68a605f2018-01-31 12:40:23 -0800433 uint8_t mLinkQuality;
Abtin Keshavarzian92b0ddc2017-07-11 09:10:54 -0700434 int8_t mLastRss;
Jonathan Hui2a9f1c72019-12-18 10:24:13 -0800435
Abtin Keshavarzian68a605f2018-01-31 12:40:23 -0800436 SuccessRateTracker mFrameErrorRate;
437 SuccessRateTracker mMessageErrorRate;
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700438};
439
440/**
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700441 * @}
442 */
443
Jonathan Hui69d98d42018-02-06 14:14:57 -0800444} // namespace ot
Abtin Keshavarziancb338982016-06-27 14:15:11 -0700445
446#endif // LINK_QUALITY_HPP_