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