1 /*
2  *  Copyright (c) 2020, 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_TLVS_HPP_
36 #define LINK_METRICS_TLVS_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/clearable.hpp"
45 #include "common/encoding.hpp"
46 #include "common/message.hpp"
47 #include "common/tlvs.hpp"
48 #include "thread/link_metrics_types.hpp"
49 
50 namespace ot {
51 namespace LinkMetrics {
52 
53 /**
54  * Defines constants related to Link Metrics Sub-TLVs.
55  *
56  */
57 class SubTlv
58 {
59 public:
60     /**
61      * Link Metrics Sub-TLV types.
62      *
63      */
64     enum Type : uint8_t
65     {
66         kReport        = 0, ///< Report Sub-TLV
67         kQueryId       = 1, ///< Query ID Sub-TLV
68         kQueryOptions  = 2, ///< Query Options Sub-TLV
69         kFwdProbingReg = 3, ///< Forward Probing Registration Sub-TLV
70         kStatus        = 5, ///< Status Sub-TLV
71         kEnhAckConfig  = 7, ///< Enhanced ACK Configuration Sub-TLV
72     };
73 };
74 
75 /**
76  * Defines Link Metrics Query ID Sub-TLV constants and types.
77  *
78  */
79 typedef UintTlvInfo<SubTlv::kQueryId, uint8_t> QueryIdSubTlv;
80 
81 /**
82  * Defines a Link Metrics Status Sub-Tlv.
83  *
84  */
85 typedef UintTlvInfo<SubTlv::kStatus, uint8_t> StatusSubTlv;
86 
87 /**
88  * Implements Link Metrics Report Sub-TLV generation and parsing.
89  *
90  */
91 OT_TOOL_PACKED_BEGIN
92 class ReportSubTlv : public Tlv, public TlvInfo<SubTlv::kReport>
93 {
94 public:
95     static constexpr uint8_t kMinLength = 2; ///< Minimum expected TLV length (type ID and u8 value).
96 
97     /**
98      * Initializes the TLV.
99      *
100      */
Init(void)101     void Init(void) { SetType(SubTlv::kReport); }
102 
103     /**
104      * Indicates whether or not the TLV appears to be well-formed.
105      *
106      * @retval true   The TLV appears to be well-formed.
107      * @retval false  The TLV does not appear to be well-formed.
108      *
109      */
IsValid(void) const110     bool IsValid(void) const { return GetLength() >= kMinLength; }
111 
112     /**
113      * Returns the Link Metrics Type ID.
114      *
115      * @returns The Link Metrics Type ID.
116      *
117      */
GetMetricsTypeId(void) const118     uint8_t GetMetricsTypeId(void) const { return mMetricsTypeId; }
119 
120     /**
121      * Sets the Link Metrics Type ID.
122      *
123      * @param[in]  aMetricsTypeId  The Link Metrics Type ID to set.
124      *
125      */
SetMetricsTypeId(uint8_t aMetricsTypeId)126     void SetMetricsTypeId(uint8_t aMetricsTypeId) { mMetricsTypeId = aMetricsTypeId; }
127 
128     /**
129      * Returns the metric value in 8 bits.
130      *
131      * @returns The metric value.
132      *
133      */
GetMetricsValue8(void) const134     uint8_t GetMetricsValue8(void) const { return mMetricsValue.m8; }
135 
136     /**
137      * Returns the metric value in 32 bits.
138      *
139      * @returns The metric value.
140      *
141      */
GetMetricsValue32(void) const142     uint32_t GetMetricsValue32(void) const { return BigEndian::HostSwap32(mMetricsValue.m32); }
143 
144     /**
145      * Sets the metric value (8 bits).
146      *
147      * @param[in]  aMetricsValue  Metrics value.
148      *
149      */
SetMetricsValue8(uint8_t aMetricsValue)150     void SetMetricsValue8(uint8_t aMetricsValue)
151     {
152         mMetricsValue.m8 = aMetricsValue;
153         SetLength(kMinLength);
154     }
155 
156     /**
157      * Sets the metric value (32 bits).
158      *
159      * @param[in]  aMetricsValue  Metrics value.
160      *
161      */
SetMetricsValue32(uint32_t aMetricsValue)162     void SetMetricsValue32(uint32_t aMetricsValue)
163     {
164         mMetricsValue.m32 = BigEndian::HostSwap32(aMetricsValue);
165         SetLength(sizeof(*this) - sizeof(Tlv));
166     }
167 
168 private:
169     uint8_t mMetricsTypeId;
170     union
171     {
172         uint8_t  m8;
173         uint32_t m32;
174     } mMetricsValue;
175 } OT_TOOL_PACKED_END;
176 
177 /**
178  * Implements Link Metrics Query Options Sub-TLV generation and parsing.
179  *
180  */
181 OT_TOOL_PACKED_BEGIN
182 class QueryOptionsSubTlv : public Tlv, public TlvInfo<SubTlv::kQueryOptions>
183 {
184 public:
185     /**
186      * Initializes the TLV.
187      *
188      */
Init(void)189     void Init(void)
190     {
191         SetType(SubTlv::kQueryOptions);
192         SetLength(0);
193     }
194 
195     /**
196      * Indicates whether or not the TLV appears to be well-formed.
197      *
198      * @retval TRUE   If the TLV appears to be well-formed.
199      * @retval FALSE  If the TLV does not appear to be well-formed.
200      *
201      */
IsValid(void) const202     bool IsValid(void) const { return GetLength() >= sizeof(uint8_t); }
203 
204 } OT_TOOL_PACKED_END;
205 
206 /**
207  * Defines Link Metrics Forward Probing Registration Sub-TLV.
208  *
209  */
210 OT_TOOL_PACKED_BEGIN
211 class FwdProbingRegSubTlv : public Tlv, public TlvInfo<SubTlv::kFwdProbingReg>
212 {
213 public:
214     static constexpr uint8_t kMinLength = sizeof(uint8_t) + sizeof(uint8_t); ///< Minimum expected TLV length
215 
216     /**
217      * Initializes the TLV.
218      *
219      */
Init(void)220     void Init(void)
221     {
222         SetType(SubTlv::kFwdProbingReg);
223         SetLength(kMinLength);
224     }
225 
226     /**
227      * Indicates whether or not the TLV appears to be well-formed.
228      *
229      * @retval true   The TLV appears to be well-formed.
230      * @retval false  The TLV does not appear to be well-formed.
231      *
232      */
IsValid(void) const233     bool IsValid(void) const { return GetLength() >= kMinLength; }
234 
235     /**
236      * Gets the Forward Series ID value.
237      *
238      * @returns The Forward Series ID.
239      *
240      */
GetSeriesId(void) const241     uint8_t GetSeriesId(void) const { return mSeriesId; }
242 
243     /**
244      * Sets the Forward Series ID value.
245      *
246      * @param[in] aSeriesId  The Forward Series ID.
247      *
248      */
SetSeriesId(uint8_t aSeriesId)249     void SetSeriesId(uint8_t aSeriesId) { mSeriesId = aSeriesId; }
250 
251     /**
252      * Gets the Forward Series Flags bit-mask.
253      *
254      * @returns The Forward Series Flags mask.
255      *
256      */
GetSeriesFlagsMask(void) const257     uint8_t GetSeriesFlagsMask(void) const { return mSeriesFlagsMask; }
258 
259     /**
260      * Sets the Forward Series Flags bit-mask
261      *
262      * @param[in] aSeriesFlagsMask  The Forward Series Flags.
263      *
264      */
SetSeriesFlagsMask(uint8_t aSeriesFlagsMask)265     void SetSeriesFlagsMask(uint8_t aSeriesFlagsMask) { mSeriesFlagsMask = aSeriesFlagsMask; }
266 
267     /**
268      * Gets the start of Type ID array.
269      *
270      * @returns The start of Type ID array. Array has `kMaxTypeIds` max length.
271      *
272      */
GetTypeIds(void)273     uint8_t *GetTypeIds(void) { return mTypeIds; }
274 
275 private:
276     uint8_t mSeriesId;
277     uint8_t mSeriesFlagsMask;
278     uint8_t mTypeIds[kMaxTypeIds];
279 } OT_TOOL_PACKED_END;
280 
281 OT_TOOL_PACKED_BEGIN
282 class EnhAckConfigSubTlv : public Tlv, public TlvInfo<SubTlv::kEnhAckConfig>
283 {
284 public:
285     static constexpr uint8_t kMinLength = sizeof(uint8_t); ///< Minimum TLV length (only `EnhAckFlags`).
286 
287     /**
288      * Initializes the TLV.
289      *
290      */
Init(void)291     void Init(void)
292     {
293         SetType(SubTlv::kEnhAckConfig);
294         SetLength(kMinLength);
295     }
296 
297     /**
298      * Indicates whether or not the TLV appears to be well-formed.
299      *
300      * @retval true   The TLV appears to be well-formed.
301      * @retval false  The TLV does not appear to be well-formed.
302      *
303      */
IsValid(void) const304     bool IsValid(void) const { return GetLength() >= kMinLength; }
305 
306     /**
307      * Gets the Enhanced ACK Flags.
308      *
309      * @returns The Enhanced ACK Flags.
310      *
311      */
GetEnhAckFlags(void) const312     uint8_t GetEnhAckFlags(void) const { return mEnhAckFlags; }
313 
314     /**
315      * Sets Enhanced ACK Flags.
316      *
317      * @param[in] aEnhAckFlags  The value of Enhanced ACK Flags.
318      *
319      */
SetEnhAckFlags(EnhAckFlags aEnhAckFlags)320     void SetEnhAckFlags(EnhAckFlags aEnhAckFlags) { mEnhAckFlags = aEnhAckFlags; }
321 
322     /**
323      * Gets the start of Type ID array.
324      *
325      * @returns The start of Type ID array. Array has `kMaxTypeIds` max length.
326      *
327      */
GetTypeIds(void)328     uint8_t *GetTypeIds(void) { return mTypeIds; }
329 
330 private:
331     uint8_t mEnhAckFlags;
332     uint8_t mTypeIds[kMaxTypeIds];
333 } OT_TOOL_PACKED_END;
334 
335 } // namespace LinkMetrics
336 } // namespace ot
337 
338 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
339 
340 #endif // LINK_METRICS_TLVS_HPP_
341