1 /*
2  *  Copyright (c) 2016-2024, 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 IEEE 802.15.4 IE (Information Element).
32  */
33 
34 #ifndef MAC_HEADER_IE_HPP_
35 #define MAC_HEADER_IE_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/as_core_type.hpp"
40 #include "common/encoding.hpp"
41 #include "common/numeric_limits.hpp"
42 #include "mac/mac_types.hpp"
43 
44 namespace ot {
45 namespace Mac {
46 
47 /**
48  * @addtogroup core-mac
49  *
50  * @{
51  *
52  */
53 
54 /**
55  * Implements IEEE 802.15.4 IE (Information Element) header generation and parsing.
56  *
57  */
58 OT_TOOL_PACKED_BEGIN
59 class HeaderIe
60 {
61 public:
62     /**
63      * Initializes the Header IE.
64      *
65      */
Init(void)66     void Init(void) { mFields.m16 = 0; }
67 
68     /**
69      * Initializes the Header IE with Id and Length.
70      *
71      * @param[in]  aId   The IE Element Id.
72      * @param[in]  aLen  The IE content length.
73      *
74      */
75     void Init(uint16_t aId, uint8_t aLen);
76 
77     /**
78      * Returns the IE Element Id.
79      *
80      * @returns the IE Element Id.
81      *
82      */
GetId(void) const83     uint16_t GetId(void) const { return (LittleEndian::HostSwap16(mFields.m16) & kIdMask) >> kIdOffset; }
84 
85     /**
86      * Sets the IE Element Id.
87      *
88      * @param[in]  aId  The IE Element Id.
89      *
90      */
SetId(uint16_t aId)91     void SetId(uint16_t aId)
92     {
93         mFields.m16 = LittleEndian::HostSwap16((LittleEndian::HostSwap16(mFields.m16) & ~kIdMask) |
94                                                ((aId << kIdOffset) & kIdMask));
95     }
96 
97     /**
98      * Returns the IE content length.
99      *
100      * @returns the IE content length.
101      *
102      */
GetLength(void) const103     uint8_t GetLength(void) const { return mFields.m8[0] & kLengthMask; }
104 
105     /**
106      * Sets the IE content length.
107      *
108      * @param[in]  aLength  The IE content length.
109      *
110      */
SetLength(uint8_t aLength)111     void SetLength(uint8_t aLength) { mFields.m8[0] = (mFields.m8[0] & ~kLengthMask) | (aLength & kLengthMask); }
112 
113 private:
114     // Header IE format:
115     //
116     // +-----------+------------+--------+
117     // | Bits: 0-6 |    7-14    |   15   |
118     // +-----------+------------+--------+
119     // | Length    | Element ID | Type=0 |
120     // +-----------+------------+--------+
121 
122     static constexpr uint8_t  kSize       = 2;
123     static constexpr uint8_t  kIdOffset   = 7;
124     static constexpr uint8_t  kLengthMask = 0x7f;
125     static constexpr uint16_t kIdMask     = 0x00ff << kIdOffset;
126 
127     union OT_TOOL_PACKED_FIELD
128     {
129         uint8_t  m8[kSize];
130         uint16_t m16;
131     } mFields;
132 
133 } OT_TOOL_PACKED_END;
134 
135 /**
136  * Implements CSL IE data structure.
137  *
138  */
139 OT_TOOL_PACKED_BEGIN
140 class CslIe
141 {
142 public:
143     static constexpr uint8_t kHeaderIeId    = 0x1a;
144     static constexpr uint8_t kIeContentSize = sizeof(uint16_t) * 2;
145 
146     /**
147      * Returns the CSL Period.
148      *
149      * @returns the CSL Period.
150      *
151      */
GetPeriod(void) const152     uint16_t GetPeriod(void) const { return LittleEndian::HostSwap16(mPeriod); }
153 
154     /**
155      * Sets the CSL Period.
156      *
157      * @param[in]  aPeriod  The CSL Period.
158      *
159      */
SetPeriod(uint16_t aPeriod)160     void SetPeriod(uint16_t aPeriod) { mPeriod = LittleEndian::HostSwap16(aPeriod); }
161 
162     /**
163      * Returns the CSL Phase.
164      *
165      * @returns the CSL Phase.
166      *
167      */
GetPhase(void) const168     uint16_t GetPhase(void) const { return LittleEndian::HostSwap16(mPhase); }
169 
170     /**
171      * Sets the CSL Phase.
172      *
173      * @param[in]  aPhase  The CSL Phase.
174      *
175      */
SetPhase(uint16_t aPhase)176     void SetPhase(uint16_t aPhase) { mPhase = LittleEndian::HostSwap16(aPhase); }
177 
178 private:
179     uint16_t mPhase;
180     uint16_t mPeriod;
181 } OT_TOOL_PACKED_END;
182 
183 /**
184  * Implements Termination2 IE.
185  *
186  * Is empty for template specialization.
187  *
188  */
189 class Termination2Ie
190 {
191 public:
192     static constexpr uint8_t kHeaderIeId    = 0x7f;
193     static constexpr uint8_t kIeContentSize = 0;
194 };
195 
196 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || \
197     OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
198 /**
199  * Implements vendor specific Header IE generation and parsing.
200  *
201  */
202 OT_TOOL_PACKED_BEGIN
203 class VendorIeHeader
204 {
205 public:
206     static constexpr uint8_t kHeaderIeId    = 0x00;
207     static constexpr uint8_t kIeContentSize = sizeof(uint8_t) * 4;
208 
209     /**
210      * Returns the Vendor OUI.
211      *
212      * @returns The Vendor OUI.
213      *
214      */
GetVendorOui(void) const215     uint32_t GetVendorOui(void) const { return LittleEndian::ReadUint24(mOui); }
216 
217     /**
218      * Sets the Vendor OUI.
219      *
220      * @param[in]  aVendorOui  A Vendor OUI.
221      *
222      */
SetVendorOui(uint32_t aVendorOui)223     void SetVendorOui(uint32_t aVendorOui) { LittleEndian::WriteUint24(aVendorOui, mOui); }
224 
225     /**
226      * Returns the Vendor IE sub-type.
227      *
228      * @returns The Vendor IE sub-type.
229      *
230      */
GetSubType(void) const231     uint8_t GetSubType(void) const { return mSubType; }
232 
233     /**
234      * Sets the Vendor IE sub-type.
235      *
236      * @param[in]  aSubType  The Vendor IE sub-type.
237      *
238      */
SetSubType(uint8_t aSubType)239     void SetSubType(uint8_t aSubType) { mSubType = aSubType; }
240 
241 private:
242     static constexpr uint8_t kOuiSize = 3;
243 
244     uint8_t mOui[kOuiSize];
245     uint8_t mSubType;
246 } OT_TOOL_PACKED_END;
247 
248 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
249 /**
250  * Implements Time Header IE generation and parsing.
251  *
252  */
253 OT_TOOL_PACKED_BEGIN
254 class TimeIe : public VendorIeHeader
255 {
256 public:
257     static constexpr uint32_t kVendorOuiNest = 0x18b430;
258     static constexpr uint8_t  kVendorIeTime  = 0x01;
259     static constexpr uint8_t  kHeaderIeId    = VendorIeHeader::kHeaderIeId;
260     static constexpr uint8_t  kIeContentSize = VendorIeHeader::kIeContentSize + sizeof(uint8_t) + sizeof(uint64_t);
261 
262     /**
263      * Initializes the time IE.
264      *
265      */
Init(void)266     void Init(void)
267     {
268         SetVendorOui(kVendorOuiNest);
269         SetSubType(kVendorIeTime);
270     }
271 
272     /**
273      * Returns the time sync sequence.
274      *
275      * @returns the time sync sequence.
276      *
277      */
GetSequence(void) const278     uint8_t GetSequence(void) const { return mSequence; }
279 
280     /**
281      * Sets the tine sync sequence.
282      *
283      * @param[in]  aSequence The time sync sequence.
284      *
285      */
SetSequence(uint8_t aSequence)286     void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
287 
288     /**
289      * Returns the network time.
290      *
291      * @returns the network time, in microseconds.
292      *
293      */
GetTime(void) const294     uint64_t GetTime(void) const { return LittleEndian::HostSwap64(mTime); }
295 
296     /**
297      * Sets the network time.
298      *
299      * @param[in]  aTime  The network time.
300      *
301      */
SetTime(uint64_t aTime)302     void SetTime(uint64_t aTime) { mTime = LittleEndian::HostSwap64(aTime); }
303 
304 private:
305     uint8_t  mSequence;
306     uint64_t mTime;
307 } OT_TOOL_PACKED_END;
308 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
309 
310 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
311 class ThreadIe
312 {
313 public:
314     static constexpr uint8_t  kHeaderIeId               = VendorIeHeader::kHeaderIeId;
315     static constexpr uint8_t  kIeContentSize            = VendorIeHeader::kIeContentSize;
316     static constexpr uint32_t kVendorOuiThreadCompanyId = 0xeab89b;
317     static constexpr uint8_t  kEnhAckProbingIe          = 0x00;
318 };
319 #endif
320 
321 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE ||
322        // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
323 
324 /**
325  * @}
326  *
327  */
328 
329 } // namespace Mac
330 } // namespace ot
331 
332 #endif // MAC_HEADER_IE_HPP_
333