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