• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * Implements IEEE 802.15.4 IE (Information Element) header generation and parsing.
55  */
56 OT_TOOL_PACKED_BEGIN
57 class HeaderIe
58 {
59 public:
60     /**
61      * Initializes the Header IE.
62      */
Init(void)63     void Init(void) { mFields.m16 = 0; }
64 
65     /**
66      * Initializes the Header IE with Id and Length.
67      *
68      * @param[in]  aId   The IE Element Id.
69      * @param[in]  aLen  The IE content length.
70      */
71     void Init(uint16_t aId, uint8_t aLen);
72 
73     /**
74      * Returns the IE Element Id.
75      *
76      * @returns the IE Element Id.
77      */
GetId(void) const78     uint16_t GetId(void) const { return (LittleEndian::HostSwap16(mFields.m16) & kIdMask) >> kIdOffset; }
79 
80     /**
81      * Sets the IE Element Id.
82      *
83      * @param[in]  aId  The IE Element Id.
84      */
SetId(uint16_t aId)85     void SetId(uint16_t aId)
86     {
87         mFields.m16 = LittleEndian::HostSwap16((LittleEndian::HostSwap16(mFields.m16) & ~kIdMask) |
88                                                ((aId << kIdOffset) & kIdMask));
89     }
90 
91     /**
92      * Returns the IE content length.
93      *
94      * @returns the IE content length.
95      */
GetLength(void) const96     uint8_t GetLength(void) const { return mFields.m8[0] & kLengthMask; }
97 
98     /**
99      * Sets the IE content length.
100      *
101      * @param[in]  aLength  The IE content length.
102      */
SetLength(uint8_t aLength)103     void SetLength(uint8_t aLength) { mFields.m8[0] = (mFields.m8[0] & ~kLengthMask) | (aLength & kLengthMask); }
104 
105 private:
106     // Header IE format:
107     //
108     // +-----------+------------+--------+
109     // | Bits: 0-6 |    7-14    |   15   |
110     // +-----------+------------+--------+
111     // | Length    | Element ID | Type=0 |
112     // +-----------+------------+--------+
113 
114     static constexpr uint8_t  kSize       = 2;
115     static constexpr uint8_t  kIdOffset   = 7;
116     static constexpr uint8_t  kLengthMask = 0x7f;
117     static constexpr uint16_t kIdMask     = 0x00ff << kIdOffset;
118 
119     union OT_TOOL_PACKED_FIELD
120     {
121         uint8_t  m8[kSize];
122         uint16_t m16;
123     } mFields;
124 
125 } OT_TOOL_PACKED_END;
126 
127 /**
128  * Implements CSL IE data structure.
129  */
130 OT_TOOL_PACKED_BEGIN
131 class CslIe
132 {
133 public:
134     static constexpr uint8_t kHeaderIeId    = 0x1a;
135     static constexpr uint8_t kIeContentSize = sizeof(uint16_t) * 2;
136 
137     /**
138      * Returns the CSL Period.
139      *
140      * @returns the CSL Period.
141      */
GetPeriod(void) const142     uint16_t GetPeriod(void) const { return LittleEndian::HostSwap16(mPeriod); }
143 
144     /**
145      * Sets the CSL Period.
146      *
147      * @param[in]  aPeriod  The CSL Period.
148      */
SetPeriod(uint16_t aPeriod)149     void SetPeriod(uint16_t aPeriod) { mPeriod = LittleEndian::HostSwap16(aPeriod); }
150 
151     /**
152      * Returns the CSL Phase.
153      *
154      * @returns the CSL Phase.
155      */
GetPhase(void) const156     uint16_t GetPhase(void) const { return LittleEndian::HostSwap16(mPhase); }
157 
158     /**
159      * Sets the CSL Phase.
160      *
161      * @param[in]  aPhase  The CSL Phase.
162      */
SetPhase(uint16_t aPhase)163     void SetPhase(uint16_t aPhase) { mPhase = LittleEndian::HostSwap16(aPhase); }
164 
165 private:
166     uint16_t mPhase;
167     uint16_t mPeriod;
168 } OT_TOOL_PACKED_END;
169 
170 /**
171  * Implements Termination2 IE.
172  *
173  * Is empty for template specialization.
174  */
175 class Termination2Ie
176 {
177 public:
178     static constexpr uint8_t kHeaderIeId    = 0x7f;
179     static constexpr uint8_t kIeContentSize = 0;
180 };
181 
182 /**
183  * Implements vendor specific Header IE generation and parsing.
184  */
185 OT_TOOL_PACKED_BEGIN
186 class VendorIeHeader
187 {
188 public:
189     static constexpr uint8_t kHeaderIeId    = 0x00;
190     static constexpr uint8_t kIeContentSize = sizeof(uint8_t) * 4;
191 
192     /**
193      * Returns the Vendor OUI.
194      *
195      * @returns The Vendor OUI.
196      */
GetVendorOui(void) const197     uint32_t GetVendorOui(void) const { return LittleEndian::ReadUint24(mOui); }
198 
199     /**
200      * Sets the Vendor OUI.
201      *
202      * @param[in]  aVendorOui  A Vendor OUI.
203      */
SetVendorOui(uint32_t aVendorOui)204     void SetVendorOui(uint32_t aVendorOui) { LittleEndian::WriteUint24(aVendorOui, mOui); }
205 
206     /**
207      * Returns the Vendor IE sub-type.
208      *
209      * @returns The Vendor IE sub-type.
210      */
GetSubType(void) const211     uint8_t GetSubType(void) const { return mSubType; }
212 
213     /**
214      * Sets the Vendor IE sub-type.
215      *
216      * @param[in]  aSubType  The Vendor IE sub-type.
217      */
SetSubType(uint8_t aSubType)218     void SetSubType(uint8_t aSubType) { mSubType = aSubType; }
219 
220 private:
221     static constexpr uint8_t kOuiSize = 3;
222 
223     uint8_t mOui[kOuiSize];
224     uint8_t mSubType;
225 } OT_TOOL_PACKED_END;
226 
227 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
228 /**
229  * Implements Time Header IE generation and parsing.
230  */
231 OT_TOOL_PACKED_BEGIN
232 class TimeIe : public VendorIeHeader
233 {
234 public:
235     static constexpr uint32_t kVendorOuiNest = 0x18b430;
236     static constexpr uint8_t  kVendorIeTime  = 0x01;
237     static constexpr uint8_t  kHeaderIeId    = VendorIeHeader::kHeaderIeId;
238     static constexpr uint8_t  kIeContentSize = VendorIeHeader::kIeContentSize + sizeof(uint8_t) + sizeof(uint64_t);
239 
240     /**
241      * Initializes the time IE.
242      */
Init(void)243     void Init(void)
244     {
245         SetVendorOui(kVendorOuiNest);
246         SetSubType(kVendorIeTime);
247     }
248 
249     /**
250      * Returns the time sync sequence.
251      *
252      * @returns the time sync sequence.
253      */
GetSequence(void) const254     uint8_t GetSequence(void) const { return mSequence; }
255 
256     /**
257      * Sets the tine sync sequence.
258      *
259      * @param[in]  aSequence The time sync sequence.
260      */
SetSequence(uint8_t aSequence)261     void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
262 
263     /**
264      * Returns the network time.
265      *
266      * @returns the network time, in microseconds.
267      */
GetTime(void) const268     uint64_t GetTime(void) const { return LittleEndian::HostSwap64(mTime); }
269 
270     /**
271      * Sets the network time.
272      *
273      * @param[in]  aTime  The network time.
274      */
SetTime(uint64_t aTime)275     void SetTime(uint64_t aTime) { mTime = LittleEndian::HostSwap64(aTime); }
276 
277 private:
278     uint8_t  mSequence;
279     uint64_t mTime;
280 } OT_TOOL_PACKED_END;
281 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
282 
283 class ThreadIe
284 {
285 public:
286     static constexpr uint8_t  kHeaderIeId               = VendorIeHeader::kHeaderIeId;
287     static constexpr uint8_t  kIeContentSize            = VendorIeHeader::kIeContentSize;
288     static constexpr uint32_t kVendorOuiThreadCompanyId = 0xeab89b;
289     static constexpr uint8_t  kEnhAckProbingIe          = 0x00;
290 };
291 
292 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
293 /**
294  * This class implements Rendezvous Time IE data structure.
295  *
296  * IEEE 802.15.4 Rendezvous Time IE contains two fields, Rendezvous Time and
297  * Wake-up Interval, but the Wake-up Interval is not used in Thread, so it is
298  * not included in this class.
299  */
300 OT_TOOL_PACKED_BEGIN
301 class RendezvousTimeIe
302 {
303 public:
304     static constexpr uint8_t kHeaderIeId    = 0x1d;
305     static constexpr uint8_t kIeContentSize = sizeof(uint16_t);
306 
307     /**
308      * This method returns the Rendezvous Time.
309      *
310      * @returns the Rendezvous Time in the units of 10 symbols.
311      */
GetRendezvousTime(void) const312     uint16_t GetRendezvousTime(void) const { return LittleEndian::HostSwap16(mRendezvousTime); }
313 
314     /**
315      * This method sets the Rendezvous Time.
316      *
317      * @param[in]  aRendezvousTime  The Rendezvous Time in the units of 10 symbols.
318      */
SetRendezvousTime(uint16_t aRendezvousTime)319     void SetRendezvousTime(uint16_t aRendezvousTime) { mRendezvousTime = LittleEndian::HostSwap16(aRendezvousTime); }
320 
321 private:
322     uint16_t mRendezvousTime;
323 } OT_TOOL_PACKED_END;
324 
325 /**
326  * Implements Connection IE data structure.
327  */
328 OT_TOOL_PACKED_BEGIN
329 class ConnectionIe : public VendorIeHeader
330 {
331 public:
332     static constexpr uint8_t kHeaderIeId      = ThreadIe::kHeaderIeId;
333     static constexpr uint8_t kIeContentSize   = ThreadIe::kIeContentSize + sizeof(uint8_t);
334     static constexpr uint8_t kThreadIeSubtype = 0x01;
335 
336     /**
337      * Initializes the Connection IE.
338      */
Init(void)339     void Init(void)
340     {
341         SetVendorOui(ThreadIe::kVendorOuiThreadCompanyId);
342         SetSubType(kThreadIeSubtype);
343         mConnectionWindow = 0;
344     }
345 
346     /**
347      * Returns the Retry Interval.
348      *
349      * The Retry Interval defines how frequently the Wake-up End Device is
350      * supposed to retry sending the Parent Request to the Wake-up Coordinator.
351      *
352      * @returns the Retry Interval in the units of Wake-up Intervals (7.5ms by default).
353      */
GetRetryInterval(void) const354     uint8_t GetRetryInterval(void) const { return (mConnectionWindow & kRetryIntervalMask) >> kRetryIntervalOffset; }
355 
356     /**
357      * Sets the Retry Interval.
358      *
359      * @param[in]  aRetryInterval  The Retry Interval in the units of Wake-up Intervals (7.5ms by default).
360      */
SetRetryInterval(uint8_t aRetryInterval)361     void SetRetryInterval(uint8_t aRetryInterval)
362     {
363         mConnectionWindow = (aRetryInterval << kRetryIntervalOffset) | (mConnectionWindow & ~kRetryIntervalMask);
364     }
365 
366     /**
367      * Returns the Retry Count.
368      *
369      * The Retry Count defines how many times the Wake-up End Device is supposed
370      * to retry sending the Parent Request to the Wakeup Coordinator.
371      *
372      * @returns the Retry Count.
373      */
GetRetryCount(void) const374     uint8_t GetRetryCount(void) const { return mConnectionWindow & kRetryCountMask; }
375 
376     /**
377      * Sets the Retry Count
378      *
379      * @param[in]  aRetryCount  The Retry Count.
380      */
SetRetryCount(uint8_t aRetryCount)381     void SetRetryCount(uint8_t aRetryCount)
382     {
383         mConnectionWindow = aRetryCount | (mConnectionWindow & ~kRetryCountMask);
384     }
385 
386 private:
387     static constexpr uint8_t kRetryIntervalOffset = 4;
388     static constexpr uint8_t kRetryIntervalMask   = 0x3 << kRetryIntervalOffset;
389     static constexpr uint8_t kRetryCountMask      = 0xf;
390 
391     uint8_t mConnectionWindow;
392 } OT_TOOL_PACKED_END;
393 #endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
394 
395 /**
396  * @}
397  */
398 
399 } // namespace Mac
400 } // namespace ot
401 
402 #endif // MAC_HEADER_IE_HPP_
403