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 Thread Link Metrics.
32 */
33
34 #include "link_metrics_types.hpp"
35
36 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
37
38 #include "common/code_utils.hpp"
39 #include "mac/mac_frame.hpp"
40
41 namespace ot {
42 namespace LinkMetrics {
43
44 //----------------------------------------------------------------------------------------------------------------------
45 // Metrics
46
ConvertToTypeIds(uint8_t aTypeIds[]) const47 uint8_t Metrics::ConvertToTypeIds(uint8_t aTypeIds[]) const
48 {
49 uint8_t count = 0;
50
51 if (mPduCount)
52 {
53 aTypeIds[count++] = TypeId::kPdu;
54 }
55
56 if (mLqi)
57 {
58 aTypeIds[count++] = TypeId::kLqi;
59 }
60
61 if (mLinkMargin)
62 {
63 aTypeIds[count++] = TypeId::kLinkMargin;
64 }
65
66 if (mRssi)
67 {
68 aTypeIds[count++] = TypeId::kRssi;
69 }
70
71 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
72 if (mReserved)
73 {
74 for (uint8_t i = 0; i < count; i++)
75 {
76 TypeId::MarkAsReserved(aTypeIds[i]);
77 }
78 }
79 #endif
80
81 return count;
82 }
83
84 //----------------------------------------------------------------------------------------------------------------------
85 // SeriesFlags
86
ConvertToMask(void) const87 uint8_t SeriesFlags::ConvertToMask(void) const
88 {
89 uint8_t mask = 0;
90
91 mask |= (mLinkProbe ? kLinkProbeFlag : 0);
92 mask |= (mMacData ? kMacDataFlag : 0);
93 mask |= (mMacDataRequest ? kMacDataRequestFlag : 0);
94 mask |= (mMacAck ? kMacAckFlag : 0);
95
96 return mask;
97 }
98
SetFrom(uint8_t aFlagsMask)99 void SeriesFlags::SetFrom(uint8_t aFlagsMask)
100 {
101 mLinkProbe = (aFlagsMask & kLinkProbeFlag);
102 mMacData = (aFlagsMask & kMacDataFlag);
103 mMacDataRequest = (aFlagsMask & kMacDataRequestFlag);
104 mMacAck = (aFlagsMask & kMacAckFlag);
105 }
106
107 //----------------------------------------------------------------------------------------------------------------------
108 // SeriesInfo
109
Init(uint8_t aSeriesId,uint8_t aSeriesFlagsMask,const Metrics & aMetrics)110 void SeriesInfo::Init(uint8_t aSeriesId, uint8_t aSeriesFlagsMask, const Metrics &aMetrics)
111 {
112 mSeriesId = aSeriesId;
113 mSeriesFlags.SetFrom(aSeriesFlagsMask);
114 mMetrics = aMetrics;
115 mRssAverager.Clear();
116 mLqiAverager.Clear();
117 mPduCount = 0;
118 }
119
AggregateLinkMetrics(uint8_t aFrameType,uint8_t aLqi,int8_t aRss)120 void SeriesInfo::AggregateLinkMetrics(uint8_t aFrameType, uint8_t aLqi, int8_t aRss)
121 {
122 if (IsFrameTypeMatch(aFrameType))
123 {
124 mPduCount++;
125 mLqiAverager.Add(aLqi);
126 IgnoreError(mRssAverager.Add(aRss));
127 }
128 }
129
IsFrameTypeMatch(uint8_t aFrameType) const130 bool SeriesInfo::IsFrameTypeMatch(uint8_t aFrameType) const
131 {
132 bool match = false;
133
134 switch (aFrameType)
135 {
136 case kSeriesTypeLinkProbe:
137 VerifyOrExit(!mSeriesFlags.IsMacDataFlagSet()); // Ignore this when Mac Data is accounted
138 match = mSeriesFlags.IsLinkProbeFlagSet();
139 break;
140 case Mac::Frame::kTypeData:
141 match = mSeriesFlags.IsMacDataFlagSet();
142 break;
143 case Mac::Frame::kTypeMacCmd:
144 match = mSeriesFlags.IsMacDataRequestFlagSet();
145 break;
146 case Mac::Frame::kTypeAck:
147 match = mSeriesFlags.IsMacAckFlagSet();
148 break;
149 default:
150 break;
151 }
152
153 exit:
154 return match;
155 }
156
157 } // namespace LinkMetrics
158 } // namespace ot
159
160 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
161