1 /* 2 * Copyright (c) 2016, 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 MAC frames. 32 */ 33 34 #ifndef MAC_FRAME_HPP_ 35 #define MAC_FRAME_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/as_core_type.hpp" 40 #include "common/const_cast.hpp" 41 #include "common/encoding.hpp" 42 #include "common/numeric_limits.hpp" 43 #include "mac/mac_types.hpp" 44 #include "meshcop/network_name.hpp" 45 46 namespace ot { 47 namespace Mac { 48 49 /** 50 * @addtogroup core-mac 51 * 52 * @{ 53 * 54 */ 55 56 /** 57 * Implements IEEE 802.15.4 IE (Information Element) header generation and parsing. 58 * 59 */ 60 OT_TOOL_PACKED_BEGIN 61 class HeaderIe 62 { 63 public: 64 /** 65 * Initializes the Header IE. 66 * 67 */ Init(void)68 void Init(void) { mFields.m16 = 0; } 69 70 /** 71 * Initializes the Header IE with Id and Length. 72 * 73 * @param[in] aId The IE Element Id. 74 * @param[in] aLen The IE content length. 75 * 76 */ 77 void Init(uint16_t aId, uint8_t aLen); 78 79 /** 80 * Returns the IE Element Id. 81 * 82 * @returns the IE Element Id. 83 * 84 */ GetId(void) const85 uint16_t GetId(void) const { return (LittleEndian::HostSwap16(mFields.m16) & kIdMask) >> kIdOffset; } 86 87 /** 88 * Sets the IE Element Id. 89 * 90 * @param[in] aId The IE Element Id. 91 * 92 */ SetId(uint16_t aId)93 void SetId(uint16_t aId) 94 { 95 mFields.m16 = LittleEndian::HostSwap16((LittleEndian::HostSwap16(mFields.m16) & ~kIdMask) | 96 ((aId << kIdOffset) & kIdMask)); 97 } 98 99 /** 100 * Returns the IE content length. 101 * 102 * @returns the IE content length. 103 * 104 */ GetLength(void) const105 uint8_t GetLength(void) const { return mFields.m8[0] & kLengthMask; } 106 107 /** 108 * Sets the IE content length. 109 * 110 * @param[in] aLength The IE content length. 111 * 112 */ SetLength(uint8_t aLength)113 void SetLength(uint8_t aLength) { mFields.m8[0] = (mFields.m8[0] & ~kLengthMask) | (aLength & kLengthMask); } 114 115 private: 116 // Header IE format: 117 // 118 // +-----------+------------+--------+ 119 // | Bits: 0-6 | 7-14 | 15 | 120 // +-----------+------------+--------+ 121 // | Length | Element ID | Type=0 | 122 // +-----------+------------+--------+ 123 124 static constexpr uint8_t kSize = 2; 125 static constexpr uint8_t kIdOffset = 7; 126 static constexpr uint8_t kLengthMask = 0x7f; 127 static constexpr uint16_t kIdMask = 0x00ff << kIdOffset; 128 129 union OT_TOOL_PACKED_FIELD 130 { 131 uint8_t m8[kSize]; 132 uint16_t m16; 133 } mFields; 134 135 } OT_TOOL_PACKED_END; 136 137 /** 138 * Implements CSL IE data structure. 139 * 140 */ 141 OT_TOOL_PACKED_BEGIN 142 class CslIe 143 { 144 public: 145 static constexpr uint8_t kHeaderIeId = 0x1a; 146 static constexpr uint8_t kIeContentSize = sizeof(uint16_t) * 2; 147 148 /** 149 * Returns the CSL Period. 150 * 151 * @returns the CSL Period. 152 * 153 */ GetPeriod(void) const154 uint16_t GetPeriod(void) const { return LittleEndian::HostSwap16(mPeriod); } 155 156 /** 157 * Sets the CSL Period. 158 * 159 * @param[in] aPeriod The CSL Period. 160 * 161 */ SetPeriod(uint16_t aPeriod)162 void SetPeriod(uint16_t aPeriod) { mPeriod = LittleEndian::HostSwap16(aPeriod); } 163 164 /** 165 * Returns the CSL Phase. 166 * 167 * @returns the CSL Phase. 168 * 169 */ GetPhase(void) const170 uint16_t GetPhase(void) const { return LittleEndian::HostSwap16(mPhase); } 171 172 /** 173 * Sets the CSL Phase. 174 * 175 * @param[in] aPhase The CSL Phase. 176 * 177 */ SetPhase(uint16_t aPhase)178 void SetPhase(uint16_t aPhase) { mPhase = LittleEndian::HostSwap16(aPhase); } 179 180 private: 181 uint16_t mPhase; 182 uint16_t mPeriod; 183 } OT_TOOL_PACKED_END; 184 185 /** 186 * Implements Termination2 IE. 187 * 188 * Is empty for template specialization. 189 * 190 */ 191 class Termination2Ie 192 { 193 public: 194 static constexpr uint8_t kHeaderIeId = 0x7f; 195 static constexpr uint8_t kIeContentSize = 0; 196 }; 197 198 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || \ 199 OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 200 /** 201 * Implements vendor specific Header IE generation and parsing. 202 * 203 */ 204 OT_TOOL_PACKED_BEGIN 205 class VendorIeHeader 206 { 207 public: 208 static constexpr uint8_t kHeaderIeId = 0x00; 209 static constexpr uint8_t kIeContentSize = sizeof(uint8_t) * 4; 210 211 /** 212 * Returns the Vendor OUI. 213 * 214 * @returns The Vendor OUI. 215 * 216 */ GetVendorOui(void) const217 uint32_t GetVendorOui(void) const { return LittleEndian::ReadUint24(mOui); } 218 219 /** 220 * Sets the Vendor OUI. 221 * 222 * @param[in] aVendorOui A Vendor OUI. 223 * 224 */ SetVendorOui(uint32_t aVendorOui)225 void SetVendorOui(uint32_t aVendorOui) { LittleEndian::WriteUint24(aVendorOui, mOui); } 226 227 /** 228 * Returns the Vendor IE sub-type. 229 * 230 * @returns The Vendor IE sub-type. 231 * 232 */ GetSubType(void) const233 uint8_t GetSubType(void) const { return mSubType; } 234 235 /** 236 * Sets the Vendor IE sub-type. 237 * 238 * @param[in] aSubType The Vendor IE sub-type. 239 * 240 */ SetSubType(uint8_t aSubType)241 void SetSubType(uint8_t aSubType) { mSubType = aSubType; } 242 243 private: 244 static constexpr uint8_t kOuiSize = 3; 245 246 uint8_t mOui[kOuiSize]; 247 uint8_t mSubType; 248 } OT_TOOL_PACKED_END; 249 250 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 251 /** 252 * Implements Time Header IE generation and parsing. 253 * 254 */ 255 OT_TOOL_PACKED_BEGIN 256 class TimeIe : public VendorIeHeader 257 { 258 public: 259 static constexpr uint32_t kVendorOuiNest = 0x18b430; 260 static constexpr uint8_t kVendorIeTime = 0x01; 261 static constexpr uint8_t kHeaderIeId = VendorIeHeader::kHeaderIeId; 262 static constexpr uint8_t kIeContentSize = VendorIeHeader::kIeContentSize + sizeof(uint8_t) + sizeof(uint64_t); 263 264 /** 265 * Initializes the time IE. 266 * 267 */ Init(void)268 void Init(void) 269 { 270 SetVendorOui(kVendorOuiNest); 271 SetSubType(kVendorIeTime); 272 } 273 274 /** 275 * Returns the time sync sequence. 276 * 277 * @returns the time sync sequence. 278 * 279 */ GetSequence(void) const280 uint8_t GetSequence(void) const { return mSequence; } 281 282 /** 283 * Sets the tine sync sequence. 284 * 285 * @param[in] aSequence The time sync sequence. 286 * 287 */ SetSequence(uint8_t aSequence)288 void SetSequence(uint8_t aSequence) { mSequence = aSequence; } 289 290 /** 291 * Returns the network time. 292 * 293 * @returns the network time, in microseconds. 294 * 295 */ GetTime(void) const296 uint64_t GetTime(void) const { return LittleEndian::HostSwap64(mTime); } 297 298 /** 299 * Sets the network time. 300 * 301 * @param[in] aTime The network time. 302 * 303 */ SetTime(uint64_t aTime)304 void SetTime(uint64_t aTime) { mTime = LittleEndian::HostSwap64(aTime); } 305 306 private: 307 uint8_t mSequence; 308 uint64_t mTime; 309 } OT_TOOL_PACKED_END; 310 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 311 312 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 313 class ThreadIe 314 { 315 public: 316 static constexpr uint8_t kHeaderIeId = VendorIeHeader::kHeaderIeId; 317 static constexpr uint8_t kIeContentSize = VendorIeHeader::kIeContentSize; 318 static constexpr uint32_t kVendorOuiThreadCompanyId = 0xeab89b; 319 static constexpr uint8_t kEnhAckProbingIe = 0x00; 320 }; 321 #endif 322 323 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || 324 // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 325 326 /** 327 * Implements IEEE 802.15.4 MAC frame generation and parsing. 328 * 329 */ 330 class Frame : public otRadioFrame 331 { 332 public: 333 /** 334 * Represents the MAC frame type. 335 * 336 * Values match the Frame Type field in Frame Control Field (FCF) as an `uint16_t`. 337 * 338 */ 339 enum Type : uint16_t 340 { 341 kTypeBeacon = 0, ///< Beacon Frame Type. 342 kTypeData = 1, ///< Data Frame Type. 343 kTypeAck = 2, ///< Ack Frame Type. 344 kTypeMacCmd = 3, ///< MAC Command Frame Type. 345 }; 346 347 /** 348 * Represents the MAC frame version. 349 * 350 * Values match the Version field in Frame Control Field (FCF) as an `uint16_t`. 351 * 352 */ 353 enum Version : uint16_t 354 { 355 kVersion2003 = 0 << 12, ///< 2003 Frame Version. 356 kVersion2006 = 1 << 12, ///< 2006 Frame Version. 357 kVersion2015 = 2 << 12, ///< 2015 Frame Version. 358 }; 359 360 /** 361 * Represents the MAC frame security level. 362 * 363 * Values match the Security Level field in Security Control Field as an `uint8_t`. 364 * 365 */ 366 enum SecurityLevel : uint8_t 367 { 368 kSecurityNone = 0, ///< No security. 369 kSecurityMic32 = 1, ///< No encryption, MIC-32 authentication. 370 kSecurityMic64 = 2, ///< No encryption, MIC-64 authentication. 371 kSecurityMic128 = 3, ///< No encryption, MIC-128 authentication. 372 kSecurityEnc = 4, ///< Encryption, no authentication 373 kSecurityEncMic32 = 5, ///< Encryption with MIC-32 authentication. 374 kSecurityEncMic64 = 6, ///< Encryption with MIC-64 authentication. 375 kSecurityEncMic128 = 7, ///< Encryption with MIC-128 authentication. 376 }; 377 378 /** 379 * Represents the MAC frame security key identifier mode. 380 * 381 * Values match the Key Identifier Mode field in Security Control Field as an `uint8_t`. 382 * 383 */ 384 enum KeyIdMode : uint8_t 385 { 386 kKeyIdMode0 = 0 << 3, ///< Key ID Mode 0 - Key is determined implicitly. 387 kKeyIdMode1 = 1 << 3, ///< Key ID Mode 1 - Key is determined from Key Index field. 388 kKeyIdMode2 = 2 << 3, ///< Key ID Mode 2 - Key is determined from 4-bytes Key Source and Index fields. 389 kKeyIdMode3 = 3 << 3, ///< Key ID Mode 3 - Key is determined from 8-bytes Key Source and Index fields. 390 }; 391 392 /** 393 * Represents a subset of MAC Command Identifiers. 394 * 395 */ 396 enum CommandId : uint8_t 397 { 398 kMacCmdAssociationRequest = 1, 399 kMacCmdAssociationResponse = 2, 400 kMacCmdDisassociationNotification = 3, 401 kMacCmdDataRequest = 4, 402 kMacCmdPanidConflictNotification = 5, 403 kMacCmdOrphanNotification = 6, 404 kMacCmdBeaconRequest = 7, 405 kMacCmdCoordinatorRealignment = 8, 406 kMacCmdGtsRequest = 9, 407 }; 408 409 static constexpr uint16_t kInfoStringSize = 128; ///< Max chars for `InfoString` (ToInfoString()). 410 411 static constexpr uint8_t kPreambleSize = 4; 412 static constexpr uint8_t kSfdSize = 1; 413 static constexpr uint8_t kPhrSize = 1; 414 static constexpr uint8_t kPhyHeaderSize = kPreambleSize + kSfdSize + kPhrSize; 415 static constexpr uint8_t kFcfSize = sizeof(uint16_t); 416 static constexpr uint8_t kDsnSize = sizeof(uint8_t); 417 static constexpr uint8_t k154FcsSize = sizeof(uint16_t); 418 static constexpr uint8_t kImmAckLength = kFcfSize + kDsnSize + k154FcsSize; 419 420 /** 421 * Defines the fixed-length `String` object returned from `ToInfoString()` method. 422 * 423 */ 424 typedef String<kInfoStringSize> InfoString; 425 426 /** 427 * Indicates whether the frame is empty (no payload). 428 * 429 * @retval TRUE The frame is empty (no PSDU payload). 430 * @retval FALSE The frame is not empty. 431 * 432 */ IsEmpty(void) const433 bool IsEmpty(void) const { return (mLength == 0); } 434 435 /** 436 * Initializes the MAC header. 437 * 438 * Determines and writes the Frame Control Field (FCF) and Security Control in the frame along with 439 * given source and destination addresses and PAN IDs. 440 * 441 * The Ack Request bit in FCF is set if there is destination and it is not broadcast and frame type @p aType is not 442 * ACK. The Frame Pending and IE Present bits are not set. 443 * 444 * @param[in] aType Frame type. 445 * @param[in] aVersion Frame version. 446 * @param[in] aAddrs Frame source and destination addresses (each can be none, short, or extended). 447 * @param[in] aPanIds Source and destination PAN IDs. 448 * @param[in] aSecurityLevel Frame security level. 449 * @param[in] aKeyIdMode Frame security key ID mode. 450 * @param[in] aSuppressSequence Whether to suppress sequence number. 451 * 452 */ 453 void InitMacHeader(Type aType, 454 Version aVersion, 455 const Addresses &aAddrs, 456 const PanIds &aPanIds, 457 SecurityLevel aSecurityLevel, 458 KeyIdMode aKeyIdMode = kKeyIdMode0, 459 bool aSuppressSequence = false); 460 461 /** 462 * Validates the frame. 463 * 464 * @retval kErrorNone Successfully parsed the MAC header. 465 * @retval kErrorParse Failed to parse through the MAC header. 466 * 467 */ 468 Error ValidatePsdu(void) const; 469 470 /** 471 * Returns the IEEE 802.15.4 Frame Type. 472 * 473 * @returns The IEEE 802.15.4 Frame Type. 474 * 475 */ GetType(void) const476 uint8_t GetType(void) const { return GetPsdu()[0] & kFcfFrameTypeMask; } 477 478 /** 479 * Returns whether the frame is an Ack frame. 480 * 481 * @retval TRUE If this is an Ack. 482 * @retval FALSE If this is not an Ack. 483 * 484 */ IsAck(void) const485 bool IsAck(void) const { return GetType() == kTypeAck; } 486 487 /** 488 * Returns the IEEE 802.15.4 Frame Version. 489 * 490 * @returns The IEEE 802.15.4 Frame Version. 491 * 492 */ GetVersion(void) const493 uint16_t GetVersion(void) const { return GetFrameControlField() & kFcfFrameVersionMask; } 494 495 /** 496 * Returns if this IEEE 802.15.4 frame's version is 2015. 497 * 498 * @returns TRUE if version is 2015, FALSE otherwise. 499 * 500 */ IsVersion2015(void) const501 bool IsVersion2015(void) const { return IsVersion2015(GetFrameControlField()); } 502 503 /** 504 * Indicates whether or not security is enabled. 505 * 506 * @retval TRUE If security is enabled. 507 * @retval FALSE If security is not enabled. 508 * 509 */ GetSecurityEnabled(void) const510 bool GetSecurityEnabled(void) const { return (GetPsdu()[0] & kFcfSecurityEnabled) != 0; } 511 512 /** 513 * Indicates whether or not the Frame Pending bit is set. 514 * 515 * @retval TRUE If the Frame Pending bit is set. 516 * @retval FALSE If the Frame Pending bit is not set. 517 * 518 */ GetFramePending(void) const519 bool GetFramePending(void) const { return (GetPsdu()[0] & kFcfFramePending) != 0; } 520 521 /** 522 * Sets the Frame Pending bit. 523 * 524 * @param[in] aFramePending The Frame Pending bit. 525 * 526 */ 527 void SetFramePending(bool aFramePending); 528 529 /** 530 * Indicates whether or not the Ack Request bit is set. 531 * 532 * @retval TRUE If the Ack Request bit is set. 533 * @retval FALSE If the Ack Request bit is not set. 534 * 535 */ GetAckRequest(void) const536 bool GetAckRequest(void) const { return (GetPsdu()[0] & kFcfAckRequest) != 0; } 537 538 /** 539 * Sets the Ack Request bit. 540 * 541 * @param[in] aAckRequest The Ack Request bit. 542 * 543 */ 544 void SetAckRequest(bool aAckRequest); 545 546 /** 547 * Indicates whether or not the PanId Compression bit is set. 548 * 549 * @retval TRUE If the PanId Compression bit is set. 550 * @retval FALSE If the PanId Compression bit is not set. 551 * 552 */ IsPanIdCompressed(void) const553 bool IsPanIdCompressed(void) const { return (GetFrameControlField() & kFcfPanidCompression) != 0; } 554 555 /** 556 * Indicates whether or not IEs present. 557 * 558 * @retval TRUE If IEs present. 559 * @retval FALSE If no IE present. 560 * 561 */ IsIePresent(void) const562 bool IsIePresent(void) const { return (GetFrameControlField() & kFcfIePresent) != 0; } 563 564 /** 565 * Sets the IE Present bit. 566 * 567 * @param[in] aIePresent The IE Present bit. 568 * 569 */ 570 void SetIePresent(bool aIePresent); 571 572 /** 573 * Returns the Sequence Number value. 574 * 575 * @returns The Sequence Number value. 576 * 577 */ 578 uint8_t GetSequence(void) const; 579 580 /** 581 * Sets the Sequence Number value. 582 * 583 * @param[in] aSequence The Sequence Number value. 584 * 585 */ 586 void SetSequence(uint8_t aSequence); 587 588 /** 589 * Indicates whether or not the Sequence Number is present. 590 * 591 * @returns TRUE if the Sequence Number is present, FALSE otherwise. 592 * 593 */ IsSequencePresent(void) const594 uint8_t IsSequencePresent(void) const { return !IsSequenceSuppressed(GetFrameControlField()); } 595 596 /** 597 * Get the size of the sequence number. 598 * 599 * @retval 0 The size of sequence number is 0, indicating it's not present. 600 * @retval 1 The size of sequence number is 1, indicating it's present. 601 * 602 */ GetSeqNumSize(void) const603 uint8_t GetSeqNumSize(void) const { return GetSeqNumSize(GetFrameControlField()); } 604 605 /** 606 * Indicates whether or not the Destination PAN ID is present. 607 * 608 * @returns TRUE if the Destination PAN ID is present, FALSE otherwise. 609 * 610 */ IsDstPanIdPresent(void) const611 bool IsDstPanIdPresent(void) const { return IsDstPanIdPresent(GetFrameControlField()); } 612 613 /** 614 * Gets the Destination PAN Identifier. 615 * 616 * @param[out] aPanId The Destination PAN Identifier. 617 * 618 * @retval kErrorNone Successfully retrieved the Destination PAN Identifier. 619 * @retval kErrorParse Failed to parse the PAN Identifier. 620 * 621 */ 622 Error GetDstPanId(PanId &aPanId) const; 623 624 /** 625 * Sets the Destination PAN Identifier. 626 * 627 * @param[in] aPanId The Destination PAN Identifier. 628 * 629 */ 630 void SetDstPanId(PanId aPanId); 631 632 /** 633 * Indicates whether or not the Destination Address is present for this object. 634 * 635 * @retval TRUE If the Destination Address is present. 636 * @retval FALSE If the Destination Address is not present. 637 * 638 */ IsDstAddrPresent() const639 bool IsDstAddrPresent() const { return IsDstAddrPresent(GetFrameControlField()); } 640 641 /** 642 * Gets the Destination Address. 643 * 644 * @param[out] aAddress The Destination Address. 645 * 646 * @retval kErrorNone Successfully retrieved the Destination Address. 647 * 648 */ 649 Error GetDstAddr(Address &aAddress) const; 650 651 /** 652 * Sets the Destination Address. 653 * 654 * @param[in] aShortAddress The Destination Address. 655 * 656 */ 657 void SetDstAddr(ShortAddress aShortAddress); 658 659 /** 660 * Sets the Destination Address. 661 * 662 * @param[in] aExtAddress The Destination Address. 663 * 664 */ 665 void SetDstAddr(const ExtAddress &aExtAddress); 666 667 /** 668 * Sets the Destination Address. 669 * 670 * @param[in] aAddress The Destination Address. 671 * 672 */ 673 void SetDstAddr(const Address &aAddress); 674 675 /** 676 * Indicates whether or not the Source Address is present for this object. 677 * 678 * @retval TRUE If the Source Address is present. 679 * @retval FALSE If the Source Address is not present. 680 * 681 */ IsSrcPanIdPresent(void) const682 bool IsSrcPanIdPresent(void) const { return IsSrcPanIdPresent(GetFrameControlField()); } 683 684 /** 685 * Gets the Source PAN Identifier. 686 * 687 * @param[out] aPanId The Source PAN Identifier. 688 * 689 * @retval kErrorNone Successfully retrieved the Source PAN Identifier. 690 * 691 */ 692 Error GetSrcPanId(PanId &aPanId) const; 693 694 /** 695 * Sets the Source PAN Identifier. 696 * 697 * @param[in] aPanId The Source PAN Identifier. 698 * 699 * @retval kErrorNone Successfully set the Source PAN Identifier. 700 * 701 */ 702 Error SetSrcPanId(PanId aPanId); 703 704 /** 705 * Indicates whether or not the Source Address is present for this object. 706 * 707 * @retval TRUE If the Source Address is present. 708 * @retval FALSE If the Source Address is not present. 709 * 710 */ IsSrcAddrPresent(void) const711 bool IsSrcAddrPresent(void) const { return IsSrcAddrPresent(GetFrameControlField()); } 712 713 /** 714 * Gets the Source Address. 715 * 716 * @param[out] aAddress The Source Address. 717 * 718 * @retval kErrorNone Successfully retrieved the Source Address. 719 * 720 */ 721 Error GetSrcAddr(Address &aAddress) const; 722 723 /** 724 * Sets the Source Address. 725 * 726 * @param[in] aShortAddress The Source Address. 727 * 728 */ 729 void SetSrcAddr(ShortAddress aShortAddress); 730 731 /** 732 * Sets the Source Address. 733 * 734 * @param[in] aExtAddress The Source Address. 735 * 736 */ 737 void SetSrcAddr(const ExtAddress &aExtAddress); 738 739 /** 740 * Sets the Source Address. 741 * 742 * @param[in] aAddress The Source Address. 743 * 744 */ 745 void SetSrcAddr(const Address &aAddress); 746 747 /** 748 * Gets the Security Control Field. 749 * 750 * @param[out] aSecurityControlField The Security Control Field. 751 * 752 * @retval kErrorNone Successfully retrieved the Security Level Identifier. 753 * @retval kErrorParse Failed to find the security control field in the frame. 754 * 755 */ 756 Error GetSecurityControlField(uint8_t &aSecurityControlField) const; 757 758 /** 759 * Sets the Security Control Field. 760 * 761 * @param[in] aSecurityControlField The Security Control Field. 762 * 763 */ 764 void SetSecurityControlField(uint8_t aSecurityControlField); 765 766 /** 767 * Gets the Security Level Identifier. 768 * 769 * @param[out] aSecurityLevel The Security Level Identifier. 770 * 771 * @retval kErrorNone Successfully retrieved the Security Level Identifier. 772 * 773 */ 774 Error GetSecurityLevel(uint8_t &aSecurityLevel) const; 775 776 /** 777 * Gets the Key Identifier Mode. 778 * 779 * @param[out] aKeyIdMode The Key Identifier Mode. 780 * 781 * @retval kErrorNone Successfully retrieved the Key Identifier Mode. 782 * 783 */ 784 Error GetKeyIdMode(uint8_t &aKeyIdMode) const; 785 786 /** 787 * Gets the Frame Counter. 788 * 789 * @param[out] aFrameCounter The Frame Counter. 790 * 791 * @retval kErrorNone Successfully retrieved the Frame Counter. 792 * 793 */ 794 Error GetFrameCounter(uint32_t &aFrameCounter) const; 795 796 /** 797 * Sets the Frame Counter. 798 * 799 * @param[in] aFrameCounter The Frame Counter. 800 * 801 */ 802 void SetFrameCounter(uint32_t aFrameCounter); 803 804 /** 805 * Returns a pointer to the Key Source. 806 * 807 * @returns A pointer to the Key Source. 808 * 809 */ 810 const uint8_t *GetKeySource(void) const; 811 812 /** 813 * Sets the Key Source. 814 * 815 * @param[in] aKeySource A pointer to the Key Source value. 816 * 817 */ 818 void SetKeySource(const uint8_t *aKeySource); 819 820 /** 821 * Gets the Key Identifier. 822 * 823 * @param[out] aKeyId The Key Identifier. 824 * 825 * @retval kErrorNone Successfully retrieved the Key Identifier. 826 * 827 */ 828 Error GetKeyId(uint8_t &aKeyId) const; 829 830 /** 831 * Sets the Key Identifier. 832 * 833 * @param[in] aKeyId The Key Identifier. 834 * 835 */ 836 void SetKeyId(uint8_t aKeyId); 837 838 /** 839 * Gets the Command ID. 840 * 841 * @param[out] aCommandId The Command ID. 842 * 843 * @retval kErrorNone Successfully retrieved the Command ID. 844 * 845 */ 846 Error GetCommandId(uint8_t &aCommandId) const; 847 848 /** 849 * Sets the Command ID. 850 * 851 * @param[in] aCommandId The Command ID. 852 * 853 * @retval kErrorNone Successfully set the Command ID. 854 * 855 */ 856 Error SetCommandId(uint8_t aCommandId); 857 858 /** 859 * Indicates whether the frame is a MAC Data Request command (data poll). 860 * 861 * For 802.15.4-2015 and above frame, the frame should be already decrypted. 862 * 863 * @returns TRUE if frame is a MAC Data Request command, FALSE otherwise. 864 * 865 */ 866 bool IsDataRequestCommand(void) const; 867 868 /** 869 * Returns the MAC Frame Length, namely the IEEE 802.15.4 PSDU length. 870 * 871 * @returns The MAC Frame Length. 872 * 873 */ GetLength(void) const874 uint16_t GetLength(void) const { return mLength; } 875 876 /** 877 * Sets the MAC Frame Length. 878 * 879 * @param[in] aLength The MAC Frame Length. 880 * 881 */ SetLength(uint16_t aLength)882 void SetLength(uint16_t aLength) { mLength = aLength; } 883 884 /** 885 * Returns the MAC header size. 886 * 887 * @returns The MAC header size. 888 * 889 */ 890 uint8_t GetHeaderLength(void) const; 891 892 /** 893 * Returns the MAC footer size. 894 * 895 * @returns The MAC footer size. 896 * 897 */ 898 uint8_t GetFooterLength(void) const; 899 900 /** 901 * Returns the current MAC Payload length. 902 * 903 * @returns The current MAC Payload length. 904 * 905 */ 906 uint16_t GetPayloadLength(void) const; 907 908 /** 909 * Returns the maximum MAC Payload length for the given MAC header and footer. 910 * 911 * @returns The maximum MAC Payload length for the given MAC header and footer. 912 * 913 */ 914 uint16_t GetMaxPayloadLength(void) const; 915 916 /** 917 * Sets the MAC Payload length. 918 * 919 */ 920 void SetPayloadLength(uint16_t aLength); 921 922 /** 923 * Returns the IEEE 802.15.4 channel used for transmission or reception. 924 * 925 * @returns The IEEE 802.15.4 channel used for transmission or reception. 926 * 927 */ GetChannel(void) const928 uint8_t GetChannel(void) const { return mChannel; } 929 930 /** 931 * Returns a pointer to the PSDU. 932 * 933 * @returns A pointer to the PSDU. 934 * 935 */ GetPsdu(void)936 uint8_t *GetPsdu(void) { return mPsdu; } 937 938 /** 939 * Returns a pointer to the PSDU. 940 * 941 * @returns A pointer to the PSDU. 942 * 943 */ GetPsdu(void) const944 const uint8_t *GetPsdu(void) const { return mPsdu; } 945 946 /** 947 * Returns a pointer to the MAC Header. 948 * 949 * @returns A pointer to the MAC Header. 950 * 951 */ GetHeader(void)952 uint8_t *GetHeader(void) { return GetPsdu(); } 953 954 /** 955 * Returns a pointer to the MAC Header. 956 * 957 * @returns A pointer to the MAC Header. 958 * 959 */ GetHeader(void) const960 const uint8_t *GetHeader(void) const { return GetPsdu(); } 961 962 /** 963 * Returns a pointer to the MAC Payload. 964 * 965 * @returns A pointer to the MAC Payload. 966 * 967 */ GetPayload(void)968 uint8_t *GetPayload(void) { return AsNonConst(AsConst(this)->GetPayload()); } 969 970 /** 971 * Returns a pointer to the MAC Payload. 972 * 973 * @returns A pointer to the MAC Payload. 974 * 975 */ 976 const uint8_t *GetPayload(void) const; 977 978 /** 979 * Returns a pointer to the MAC Footer. 980 * 981 * @returns A pointer to the MAC Footer. 982 * 983 */ GetFooter(void)984 uint8_t *GetFooter(void) { return AsNonConst(AsConst(this)->GetFooter()); } 985 986 /** 987 * Returns a pointer to the MAC Footer. 988 * 989 * @returns A pointer to the MAC Footer. 990 * 991 */ 992 const uint8_t *GetFooter(void) const; 993 994 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 995 996 /** 997 * Returns a pointer to the vendor specific Time IE. 998 * 999 * @returns A pointer to the Time IE, `nullptr` if not found. 1000 * 1001 */ GetTimeIe(void)1002 TimeIe *GetTimeIe(void) { return AsNonConst(AsConst(this)->GetTimeIe()); } 1003 1004 /** 1005 * Returns a pointer to the vendor specific Time IE. 1006 * 1007 * @returns A pointer to the Time IE, `nullptr` if not found. 1008 * 1009 */ 1010 const TimeIe *GetTimeIe(void) const; 1011 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1012 1013 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 1014 /** 1015 * Appends an Header IE at specified index in this frame. 1016 * 1017 * Also sets the IE present bit in the Frame Control Field (FCF). 1018 * 1019 * @param[in,out] aIndex The index to append IE. If `aIndex` is `0` on input, this method finds the index 1020 * for the first IE and appends the IE at that position. If the position is not found 1021 * successfully, `aIndex` will be set to `kInvalidIndex`. Otherwise the IE will be 1022 * appended at `aIndex` on input. And on output, `aIndex` will be set to the end of the 1023 * IE just appended. 1024 * 1025 * @tparam IeType The Header IE type, it MUST contain a constant `kHeaderIeId` equal to the IE's Id 1026 * and a constant `kIeContentSize` indicating the IE body's size. 1027 * 1028 * @retval kErrorNone Successfully appended the Header IE. 1029 * @retval kErrorNotFound The position for first IE is not found. 1030 * 1031 */ 1032 template <typename IeType> Error AppendHeaderIeAt(uint8_t &aIndex); 1033 1034 /** 1035 * Returns a pointer to the Header IE. 1036 * 1037 * @param[in] aIeId The Element Id of the Header IE. 1038 * 1039 * @returns A pointer to the Header IE, `nullptr` if not found. 1040 * 1041 */ GetHeaderIe(uint8_t aIeId)1042 uint8_t *GetHeaderIe(uint8_t aIeId) { return AsNonConst(AsConst(this)->GetHeaderIe(aIeId)); } 1043 1044 /** 1045 * Returns a pointer to the Header IE. 1046 * 1047 * @param[in] aIeId The Element Id of the Header IE. 1048 * 1049 * @returns A pointer to the Header IE, `nullptr` if not found. 1050 * 1051 */ 1052 const uint8_t *GetHeaderIe(uint8_t aIeId) const; 1053 1054 /** 1055 * Returns a pointer to a specific Thread IE. 1056 * 1057 * A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`. 1058 * 1059 * @param[in] aSubType The sub type of the Thread IE. 1060 * 1061 * @returns A pointer to the Thread IE, `nullptr` if not found. 1062 * 1063 */ GetThreadIe(uint8_t aSubType)1064 uint8_t *GetThreadIe(uint8_t aSubType) { return AsNonConst(AsConst(this)->GetThreadIe(aSubType)); } 1065 1066 /** 1067 * Returns a pointer to a specific Thread IE. 1068 * 1069 * A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`. 1070 * 1071 * @param[in] aSubType The sub type of the Thread IE. 1072 * 1073 * @returns A pointer to the Thread IE, `nullptr` if not found. 1074 * 1075 */ 1076 const uint8_t *GetThreadIe(uint8_t aSubType) const; 1077 1078 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 1079 /** 1080 * Finds CSL IE in the frame and modify its content. 1081 * 1082 * @param[in] aCslPeriod CSL Period in CSL IE. 1083 * @param[in] aCslPhase CSL Phase in CSL IE. 1084 * 1085 */ 1086 void SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase); 1087 1088 /** 1089 * Indicates whether or not the frame contains CSL IE. 1090 * 1091 * @retval TRUE If the frame contains CSL IE. 1092 * @retval FALSE If the frame doesn't contain CSL IE. 1093 * 1094 */ 1095 bool HasCslIe(void) const; 1096 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 1097 1098 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE) 1099 /** 1100 * Returns a pointer to a CSL IE. 1101 * 1102 * @returns A pointer to the CSL IE, `nullptr` if not found. 1103 * 1104 */ 1105 const CslIe *GetCslIe(void) const; 1106 1107 /** 1108 * Returns a pointer to a CSL IE. 1109 * 1110 * @returns A pointer to the CSL IE, `nullptr` if not found. 1111 * 1112 */ GetCslIe(void)1113 CslIe *GetCslIe(void) { return AsNonConst(AsConst(this)->GetCslIe()); } 1114 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE) 1115 1116 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 1117 /** 1118 * Finds Enhanced ACK Probing (Vendor Specific) IE and set its value. 1119 * 1120 * @param[in] aValue A pointer to the value to set. 1121 * @param[in] aLen The length of @p aValue. 1122 * 1123 */ 1124 void SetEnhAckProbingIe(const uint8_t *aValue, uint8_t aLen); 1125 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 1126 1127 #endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 1128 1129 #if OPENTHREAD_CONFIG_MULTI_RADIO 1130 /** 1131 * Gets the radio link type of the frame. 1132 * 1133 * @returns Frame's radio link type. 1134 * 1135 */ GetRadioType(void) const1136 RadioType GetRadioType(void) const { return static_cast<RadioType>(mRadioType); } 1137 1138 /** 1139 * Sets the radio link type of the frame. 1140 * 1141 * @param[in] aRadioType A radio link type. 1142 * 1143 */ SetRadioType(RadioType aRadioType)1144 void SetRadioType(RadioType aRadioType) { mRadioType = static_cast<uint8_t>(aRadioType); } 1145 #endif 1146 1147 /** 1148 * Returns the maximum transmission unit size (MTU). 1149 * 1150 * @returns The maximum transmission unit (MTU). 1151 * 1152 */ GetMtu(void) const1153 uint16_t GetMtu(void) const 1154 #if !OPENTHREAD_CONFIG_MULTI_RADIO && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE 1155 { 1156 return OT_RADIO_FRAME_MAX_SIZE; 1157 } 1158 #else 1159 ; 1160 #endif 1161 1162 /** 1163 * Returns the FCS size. 1164 * 1165 * @returns This method returns the FCS size. 1166 * 1167 */ GetFcsSize(void) const1168 uint8_t GetFcsSize(void) const 1169 #if !OPENTHREAD_CONFIG_MULTI_RADIO && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE 1170 { 1171 return k154FcsSize; 1172 } 1173 #else 1174 ; 1175 #endif 1176 1177 /** 1178 * Returns information about the frame object as an `InfoString` object. 1179 * 1180 * @returns An `InfoString` containing info about the frame. 1181 * 1182 */ 1183 InfoString ToInfoString(void) const; 1184 1185 /** 1186 * Returns the Frame Control field of the frame. 1187 * 1188 * @returns The Frame Control field. 1189 * 1190 */ 1191 uint16_t GetFrameControlField(void) const; 1192 1193 protected: 1194 static constexpr uint8_t kSecurityControlSize = sizeof(uint8_t); 1195 static constexpr uint8_t kFrameCounterSize = sizeof(uint32_t); 1196 static constexpr uint8_t kCommandIdSize = sizeof(uint8_t); 1197 static constexpr uint8_t kKeyIndexSize = sizeof(uint8_t); 1198 1199 static constexpr uint16_t kFcfFrameTypeMask = 7 << 0; 1200 static constexpr uint16_t kFcfSecurityEnabled = 1 << 3; 1201 static constexpr uint16_t kFcfFramePending = 1 << 4; 1202 static constexpr uint16_t kFcfAckRequest = 1 << 5; 1203 static constexpr uint16_t kFcfPanidCompression = 1 << 6; 1204 static constexpr uint16_t kFcfSequenceSupression = 1 << 8; 1205 static constexpr uint16_t kFcfIePresent = 1 << 9; 1206 static constexpr uint16_t kFcfDstAddrNone = 0 << 10; 1207 static constexpr uint16_t kFcfDstAddrShort = 2 << 10; 1208 static constexpr uint16_t kFcfDstAddrExt = 3 << 10; 1209 static constexpr uint16_t kFcfDstAddrMask = 3 << 10; 1210 static constexpr uint16_t kFcfFrameVersionMask = 3 << 12; 1211 static constexpr uint16_t kFcfSrcAddrNone = 0 << 14; 1212 static constexpr uint16_t kFcfSrcAddrShort = 2 << 14; 1213 static constexpr uint16_t kFcfSrcAddrExt = 3 << 14; 1214 static constexpr uint16_t kFcfSrcAddrMask = 3 << 14; 1215 1216 static constexpr uint8_t kSecLevelMask = 7 << 0; 1217 static constexpr uint8_t kKeyIdModeMask = 3 << 3; 1218 1219 static constexpr uint8_t kMic0Size = 0; 1220 static constexpr uint8_t kMic32Size = 32 / kBitsPerByte; 1221 static constexpr uint8_t kMic64Size = 64 / kBitsPerByte; 1222 static constexpr uint8_t kMic128Size = 128 / kBitsPerByte; 1223 static constexpr uint8_t kMaxMicSize = kMic128Size; 1224 1225 static constexpr uint8_t kKeySourceSizeMode0 = 0; 1226 static constexpr uint8_t kKeySourceSizeMode1 = 0; 1227 static constexpr uint8_t kKeySourceSizeMode2 = 4; 1228 static constexpr uint8_t kKeySourceSizeMode3 = 8; 1229 1230 static constexpr uint8_t kInvalidIndex = 0xff; 1231 static constexpr uint8_t kInvalidSize = kInvalidIndex; 1232 static constexpr uint8_t kMaxPsduSize = kInvalidSize - 1; 1233 static constexpr uint8_t kSequenceIndex = kFcfSize; 1234 1235 void SetFrameControlField(uint16_t aFcf); 1236 uint8_t FindDstPanIdIndex(void) const; 1237 uint8_t FindDstAddrIndex(void) const; 1238 uint8_t FindSrcPanIdIndex(void) const; 1239 uint8_t FindSrcAddrIndex(void) const; 1240 uint8_t SkipAddrFieldIndex(void) const; 1241 uint8_t FindSecurityHeaderIndex(void) const; 1242 uint8_t SkipSecurityHeaderIndex(void) const; 1243 uint8_t FindPayloadIndex(void) const; 1244 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 1245 uint8_t FindHeaderIeIndex(void) const; 1246 1247 Error InitIeHeaderAt(uint8_t &aIndex, uint8_t ieId, uint8_t ieContentSize); 1248 template <typename IeType> void InitIeContentAt(uint8_t &aIndex); 1249 #endif 1250 1251 static uint8_t GetKeySourceLength(uint8_t aKeyIdMode); 1252 IsDstAddrPresent(uint16_t aFcf)1253 static bool IsDstAddrPresent(uint16_t aFcf) { return (aFcf & kFcfDstAddrMask) != kFcfDstAddrNone; } 1254 static bool IsDstPanIdPresent(uint16_t aFcf); IsSequenceSuppressed(uint16_t aFcf)1255 static bool IsSequenceSuppressed(uint16_t aFcf) 1256 { 1257 return (aFcf & (kFcfSequenceSupression | kFcfFrameVersionMask)) == (kFcfSequenceSupression | kVersion2015); 1258 } GetSeqNumSize(uint16_t aFcf)1259 static uint8_t GetSeqNumSize(uint16_t aFcf) { return !IsSequenceSuppressed(aFcf) ? kDsnSize : 0; } 1260 IsSrcAddrPresent(uint16_t aFcf)1261 static bool IsSrcAddrPresent(uint16_t aFcf) { return (aFcf & kFcfSrcAddrMask) != kFcfSrcAddrNone; } 1262 static bool IsSrcPanIdPresent(uint16_t aFcf); IsVersion2015(uint16_t aFcf)1263 static bool IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kVersion2015; } 1264 1265 static uint8_t CalculateAddrFieldSize(uint16_t aFcf); 1266 static uint8_t CalculateSecurityHeaderSize(uint8_t aSecurityControl); 1267 static uint8_t CalculateMicSize(uint8_t aSecurityControl); 1268 }; 1269 1270 /** 1271 * Supports received IEEE 802.15.4 MAC frame processing. 1272 * 1273 */ 1274 class RxFrame : public Frame 1275 { 1276 public: 1277 friend class TxFrame; 1278 1279 /** 1280 * Returns the RSSI in dBm used for reception. 1281 * 1282 * @returns The RSSI in dBm used for reception. 1283 * 1284 */ GetRssi(void) const1285 int8_t GetRssi(void) const { return mInfo.mRxInfo.mRssi; } 1286 1287 /** 1288 * Sets the RSSI in dBm used for reception. 1289 * 1290 * @param[in] aRssi The RSSI in dBm used for reception. 1291 * 1292 */ SetRssi(int8_t aRssi)1293 void SetRssi(int8_t aRssi) { mInfo.mRxInfo.mRssi = aRssi; } 1294 1295 /** 1296 * Returns the receive Link Quality Indicator. 1297 * 1298 * @returns The receive Link Quality Indicator. 1299 * 1300 */ GetLqi(void) const1301 uint8_t GetLqi(void) const { return mInfo.mRxInfo.mLqi; } 1302 1303 /** 1304 * Sets the receive Link Quality Indicator. 1305 * 1306 * @param[in] aLqi The receive Link Quality Indicator. 1307 * 1308 */ SetLqi(uint8_t aLqi)1309 void SetLqi(uint8_t aLqi) { mInfo.mRxInfo.mLqi = aLqi; } 1310 1311 /** 1312 * Indicates whether or not the received frame is acknowledged with frame pending set. 1313 * 1314 * @retval TRUE This frame is acknowledged with frame pending set. 1315 * @retval FALSE This frame is acknowledged with frame pending not set. 1316 * 1317 */ IsAckedWithFramePending(void) const1318 bool IsAckedWithFramePending(void) const { return mInfo.mRxInfo.mAckedWithFramePending; } 1319 1320 /** 1321 * Returns the timestamp when the frame was received. 1322 * 1323 * The value SHALL be the time of the local radio clock in 1324 * microseconds when the end of the SFD (or equivalently: the start 1325 * of the first symbol of the PHR) was present at the local antenna, 1326 * see the definition of a "symbol boundary" in IEEE 802.15.4-2020, 1327 * section 6.5.2 or equivalently the RMARKER definition in section 1328 * 6.9.1 (albeit both unrelated to OT). 1329 * 1330 * The time is relative to the local radio clock as defined by 1331 * `otPlatRadioGetNow`. 1332 * 1333 * @returns The timestamp in microseconds. 1334 */ GetTimestamp(void) const1335 const uint64_t &GetTimestamp(void) const { return mInfo.mRxInfo.mTimestamp; } 1336 1337 /** 1338 * Performs AES CCM on the frame which is received. 1339 * 1340 * @param[in] aExtAddress A reference to the extended address, which will be used to generate nonce 1341 * for AES CCM computation. 1342 * @param[in] aMacKey A reference to the MAC key to decrypt the received frame. 1343 * 1344 * @retval kErrorNone Process of received frame AES CCM succeeded. 1345 * @retval kErrorSecurity Received frame MIC check failed. 1346 * 1347 */ 1348 Error ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const KeyMaterial &aMacKey); 1349 1350 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1351 /** 1352 * Gets the offset to network time. 1353 * 1354 * @returns The offset to network time. 1355 * 1356 */ ComputeNetworkTimeOffset(void) const1357 int64_t ComputeNetworkTimeOffset(void) const 1358 { 1359 return static_cast<int64_t>(GetTimeIe()->GetTime() - GetTimestamp()); 1360 } 1361 1362 /** 1363 * Gets the time sync sequence. 1364 * 1365 * @returns The time sync sequence. 1366 * 1367 */ ReadTimeSyncSeq(void) const1368 uint8_t ReadTimeSyncSeq(void) const { return GetTimeIe()->GetSequence(); } 1369 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1370 }; 1371 1372 /** 1373 * Supports IEEE 802.15.4 MAC frame generation for transmission. 1374 * 1375 */ 1376 class TxFrame : public Frame 1377 { 1378 public: 1379 /** 1380 * Sets the channel on which to send the frame. 1381 * 1382 * It also sets the `RxChannelAfterTxDone` to the same channel. 1383 * 1384 * @param[in] aChannel The channel used for transmission. 1385 * 1386 */ SetChannel(uint8_t aChannel)1387 void SetChannel(uint8_t aChannel) 1388 { 1389 mChannel = aChannel; 1390 SetRxChannelAfterTxDone(aChannel); 1391 } 1392 1393 /** 1394 * Sets TX power to send the frame. 1395 * 1396 * @param[in] aTxPower The tx power used for transmission. 1397 * 1398 */ SetTxPower(int8_t aTxPower)1399 void SetTxPower(int8_t aTxPower) { mInfo.mTxInfo.mTxPower = aTxPower; } 1400 1401 /** 1402 * Gets the RX channel after frame TX is done. 1403 * 1404 * @returns The RX channel after frame TX is done. 1405 * 1406 */ GetRxChannelAfterTxDone(void) const1407 uint8_t GetRxChannelAfterTxDone(void) const { return mInfo.mTxInfo.mRxChannelAfterTxDone; } 1408 1409 /** 1410 * Sets the RX channel after frame TX is done. 1411 * 1412 * @param[in] aChannel The RX channel after frame TX is done. 1413 * 1414 */ SetRxChannelAfterTxDone(uint8_t aChannel)1415 void SetRxChannelAfterTxDone(uint8_t aChannel) { mInfo.mTxInfo.mRxChannelAfterTxDone = aChannel; } 1416 1417 /** 1418 * Returns the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel 1419 * access failure. 1420 * 1421 * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006. 1422 * 1423 * @returns The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access 1424 * failure. 1425 * 1426 */ GetMaxCsmaBackoffs(void) const1427 uint8_t GetMaxCsmaBackoffs(void) const { return mInfo.mTxInfo.mMaxCsmaBackoffs; } 1428 1429 /** 1430 * Sets the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel 1431 * access failure. 1432 * 1433 * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006. 1434 * 1435 * @param[in] aMaxCsmaBackoffs The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring 1436 * a channel access failure. 1437 * 1438 */ SetMaxCsmaBackoffs(uint8_t aMaxCsmaBackoffs)1439 void SetMaxCsmaBackoffs(uint8_t aMaxCsmaBackoffs) { mInfo.mTxInfo.mMaxCsmaBackoffs = aMaxCsmaBackoffs; } 1440 1441 /** 1442 * Returns the maximum number of retries allowed after a transmission failure. 1443 * 1444 * Equivalent to macMaxFrameRetries in IEEE 802.15.4-2006. 1445 * 1446 * @returns The maximum number of retries allowed after a transmission failure. 1447 * 1448 */ GetMaxFrameRetries(void) const1449 uint8_t GetMaxFrameRetries(void) const { return mInfo.mTxInfo.mMaxFrameRetries; } 1450 1451 /** 1452 * Sets the maximum number of retries allowed after a transmission failure. 1453 * 1454 * Equivalent to macMaxFrameRetries in IEEE 802.15.4-2006. 1455 * 1456 * @param[in] aMaxFrameRetries The maximum number of retries allowed after a transmission failure. 1457 * 1458 */ SetMaxFrameRetries(uint8_t aMaxFrameRetries)1459 void SetMaxFrameRetries(uint8_t aMaxFrameRetries) { mInfo.mTxInfo.mMaxFrameRetries = aMaxFrameRetries; } 1460 1461 /** 1462 * Indicates whether or not the frame is a retransmission. 1463 * 1464 * @retval TRUE Frame is a retransmission 1465 * @retval FALSE This is a new frame and not a retransmission of an earlier frame. 1466 * 1467 */ IsARetransmission(void) const1468 bool IsARetransmission(void) const { return mInfo.mTxInfo.mIsARetx; } 1469 1470 /** 1471 * Sets the retransmission flag attribute. 1472 * 1473 * @param[in] aIsARetx TRUE if frame is a retransmission of an earlier frame, FALSE otherwise. 1474 * 1475 */ SetIsARetransmission(bool aIsARetx)1476 void SetIsARetransmission(bool aIsARetx) { mInfo.mTxInfo.mIsARetx = aIsARetx; } 1477 1478 /** 1479 * Indicates whether or not CSMA-CA is enabled. 1480 * 1481 * @retval TRUE CSMA-CA is enabled. 1482 * @retval FALSE CSMA-CA is not enabled is not enabled. 1483 * 1484 */ IsCsmaCaEnabled(void) const1485 bool IsCsmaCaEnabled(void) const { return mInfo.mTxInfo.mCsmaCaEnabled; } 1486 1487 /** 1488 * Sets the CSMA-CA enabled attribute. 1489 * 1490 * @param[in] aCsmaCaEnabled TRUE if CSMA-CA must be enabled for this packet, FALSE otherwise. 1491 * 1492 */ SetCsmaCaEnabled(bool aCsmaCaEnabled)1493 void SetCsmaCaEnabled(bool aCsmaCaEnabled) { mInfo.mTxInfo.mCsmaCaEnabled = aCsmaCaEnabled; } 1494 1495 /** 1496 * Returns the key used for frame encryption and authentication (AES CCM). 1497 * 1498 * @returns The pointer to the key. 1499 * 1500 */ GetAesKey(void) const1501 const Mac::KeyMaterial &GetAesKey(void) const 1502 { 1503 return *static_cast<const Mac::KeyMaterial *>(mInfo.mTxInfo.mAesKey); 1504 } 1505 1506 /** 1507 * Sets the key used for frame encryption and authentication (AES CCM). 1508 * 1509 * @param[in] aAesKey The pointer to the key. 1510 * 1511 */ SetAesKey(const Mac::KeyMaterial & aAesKey)1512 void SetAesKey(const Mac::KeyMaterial &aAesKey) { mInfo.mTxInfo.mAesKey = &aAesKey; } 1513 1514 /** 1515 * Copies the PSDU and all attributes (except for frame link type) from another frame. 1516 * 1517 * @note This method performs a deep copy meaning the content of PSDU buffer from the given frame is copied into 1518 * the PSDU buffer of the current frame. 1519 1520 * @param[in] aFromFrame The frame to copy from. 1521 * 1522 */ 1523 void CopyFrom(const TxFrame &aFromFrame); 1524 1525 /** 1526 * Performs AES CCM on the frame which is going to be sent. 1527 * 1528 * @param[in] aExtAddress A reference to the extended address, which will be used to generate nonce 1529 * for AES CCM computation. 1530 * 1531 */ 1532 void ProcessTransmitAesCcm(const ExtAddress &aExtAddress); 1533 1534 /** 1535 * Indicates whether or not the frame has security processed. 1536 * 1537 * @retval TRUE The frame already has security processed. 1538 * @retval FALSE The frame does not have security processed. 1539 * 1540 */ IsSecurityProcessed(void) const1541 bool IsSecurityProcessed(void) const { return mInfo.mTxInfo.mIsSecurityProcessed; } 1542 1543 /** 1544 * Sets the security processed flag attribute. 1545 * 1546 * @param[in] aIsSecurityProcessed TRUE if the frame already has security processed. 1547 * 1548 */ SetIsSecurityProcessed(bool aIsSecurityProcessed)1549 void SetIsSecurityProcessed(bool aIsSecurityProcessed) 1550 { 1551 mInfo.mTxInfo.mIsSecurityProcessed = aIsSecurityProcessed; 1552 } 1553 1554 /** 1555 * Indicates whether or not the frame contains the CSL IE. 1556 * 1557 * @retval TRUE The frame contains the CSL IE. 1558 * @retval FALSE The frame does not contain the CSL IE. 1559 * 1560 */ IsCslIePresent(void) const1561 bool IsCslIePresent(void) const { return mInfo.mTxInfo.mCslPresent; } 1562 1563 /** 1564 * Sets the CSL IE present flag. 1565 * 1566 * @param[in] aCslPresent TRUE if the frame contains the CSL IE. 1567 */ SetCslIePresent(bool aCslPresent)1568 void SetCslIePresent(bool aCslPresent) { mInfo.mTxInfo.mCslPresent = aCslPresent; } 1569 1570 /** 1571 * Indicates whether or not the frame header is updated. 1572 * 1573 * @retval TRUE The frame already has the header updated. 1574 * @retval FALSE The frame does not have the header updated. 1575 * 1576 */ IsHeaderUpdated(void) const1577 bool IsHeaderUpdated(void) const { return mInfo.mTxInfo.mIsHeaderUpdated; } 1578 1579 /** 1580 * Sets the header updated flag attribute. 1581 * 1582 * @param[in] aIsHeaderUpdated TRUE if the frame header is updated. 1583 * 1584 */ SetIsHeaderUpdated(bool aIsHeaderUpdated)1585 void SetIsHeaderUpdated(bool aIsHeaderUpdated) { mInfo.mTxInfo.mIsHeaderUpdated = aIsHeaderUpdated; } 1586 1587 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1588 /** 1589 * Sets the Time IE offset. 1590 * 1591 * @param[in] aOffset The Time IE offset, 0 means no Time IE. 1592 * 1593 */ SetTimeIeOffset(uint8_t aOffset)1594 void SetTimeIeOffset(uint8_t aOffset) { mInfo.mTxInfo.mIeInfo->mTimeIeOffset = aOffset; } 1595 1596 /** 1597 * Gets the Time IE offset. 1598 * 1599 * @returns The Time IE offset, 0 means no Time IE. 1600 * 1601 */ GetTimeIeOffset(void) const1602 uint8_t GetTimeIeOffset(void) const { return mInfo.mTxInfo.mIeInfo->mTimeIeOffset; } 1603 1604 /** 1605 * Sets the offset to network time. 1606 * 1607 * @param[in] aNetworkTimeOffset The offset to network time. 1608 * 1609 */ SetNetworkTimeOffset(int64_t aNetworkTimeOffset)1610 void SetNetworkTimeOffset(int64_t aNetworkTimeOffset) 1611 { 1612 mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset = aNetworkTimeOffset; 1613 } 1614 1615 /** 1616 * Sets the time sync sequence. 1617 * 1618 * @param[in] aTimeSyncSeq The time sync sequence. 1619 * 1620 */ SetTimeSyncSeq(uint8_t aTimeSyncSeq)1621 void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { mInfo.mTxInfo.mIeInfo->mTimeSyncSeq = aTimeSyncSeq; } 1622 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1623 1624 /** 1625 * Generate Imm-Ack in this frame object. 1626 * 1627 * @param[in] aFrame A reference to the frame received. 1628 * @param[in] aIsFramePending Value of the ACK's frame pending bit. 1629 * 1630 */ 1631 void GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending); 1632 1633 /** 1634 * Generate Enh-Ack in this frame object. 1635 * 1636 * @param[in] aRxFrame A reference to the received frame. 1637 * @param[in] aIsFramePending Value of the ACK's frame pending bit. 1638 * @param[in] aIeData A pointer to the IE data portion of the ACK to be sent. 1639 * @param[in] aIeLength The length of IE data portion of the ACK to be sent. 1640 * 1641 * @retval kErrorNone Successfully generated Enh Ack. 1642 * @retval kErrorParse @p aRxFrame has incorrect format. 1643 * 1644 */ 1645 Error GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength); 1646 1647 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 1648 /** 1649 * Set TX delay field for the frame. 1650 * 1651 * @param[in] aTxDelay The delay time for the TX frame. 1652 * 1653 */ SetTxDelay(uint32_t aTxDelay)1654 void SetTxDelay(uint32_t aTxDelay) { mInfo.mTxInfo.mTxDelay = aTxDelay; } 1655 1656 /** 1657 * Set TX delay base time field for the frame. 1658 * 1659 * @param[in] aTxDelayBaseTime The delay base time for the TX frame. 1660 * 1661 */ SetTxDelayBaseTime(uint32_t aTxDelayBaseTime)1662 void SetTxDelayBaseTime(uint32_t aTxDelayBaseTime) { mInfo.mTxInfo.mTxDelayBaseTime = aTxDelayBaseTime; } 1663 #endif 1664 }; 1665 1666 OT_TOOL_PACKED_BEGIN 1667 class Beacon 1668 { 1669 public: 1670 static constexpr uint16_t kSuperFrameSpec = 0x0fff; ///< Superframe Specification value. 1671 1672 /** 1673 * Initializes the Beacon message. 1674 * 1675 */ Init(void)1676 void Init(void) 1677 { 1678 mSuperframeSpec = LittleEndian::HostSwap16(kSuperFrameSpec); 1679 mGtsSpec = 0; 1680 mPendingAddressSpec = 0; 1681 } 1682 1683 /** 1684 * Indicates whether or not the beacon appears to be a valid Thread Beacon message. 1685 * 1686 * @retval TRUE If the beacon appears to be a valid Thread Beacon message. 1687 * @retval FALSE If the beacon does not appear to be a valid Thread Beacon message. 1688 * 1689 */ IsValid(void) const1690 bool IsValid(void) const 1691 { 1692 return (mSuperframeSpec == LittleEndian::HostSwap16(kSuperFrameSpec)) && (mGtsSpec == 0) && 1693 (mPendingAddressSpec == 0); 1694 } 1695 1696 /** 1697 * Returns the pointer to the beacon payload. 1698 * 1699 * @returns A pointer to the beacon payload. 1700 * 1701 */ GetPayload(void)1702 uint8_t *GetPayload(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(*this); } 1703 1704 /** 1705 * Returns the pointer to the beacon payload. 1706 * 1707 * @returns A pointer to the beacon payload. 1708 * 1709 */ GetPayload(void) const1710 const uint8_t *GetPayload(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); } 1711 1712 private: 1713 uint16_t mSuperframeSpec; 1714 uint8_t mGtsSpec; 1715 uint8_t mPendingAddressSpec; 1716 } OT_TOOL_PACKED_END; 1717 1718 /** 1719 * Implements IEEE 802.15.4 Beacon Payload generation and parsing. 1720 * 1721 */ 1722 OT_TOOL_PACKED_BEGIN 1723 class BeaconPayload 1724 { 1725 public: 1726 static constexpr uint8_t kProtocolId = 3; ///< Thread Protocol ID. 1727 static constexpr uint8_t kProtocolVersion = 2; ///< Thread Protocol version. 1728 static constexpr uint8_t kVersionOffset = 4; ///< Version field bit offset. 1729 static constexpr uint8_t kVersionMask = 0xf << kVersionOffset; ///< Version field mask. 1730 static constexpr uint8_t kNativeFlag = 1 << 3; ///< Native Commissioner flag. 1731 static constexpr uint8_t kJoiningFlag = 1 << 0; ///< Joining Permitted flag. 1732 1733 /** 1734 * Initializes the Beacon Payload. 1735 * 1736 */ Init(void)1737 void Init(void) 1738 { 1739 mProtocolId = kProtocolId; 1740 mFlags = kProtocolVersion << kVersionOffset; 1741 } 1742 1743 /** 1744 * Indicates whether or not the beacon appears to be a valid Thread Beacon Payload. 1745 * 1746 * @retval TRUE If the beacon appears to be a valid Thread Beacon Payload. 1747 * @retval FALSE If the beacon does not appear to be a valid Thread Beacon Payload. 1748 * 1749 */ IsValid(void) const1750 bool IsValid(void) const { return (mProtocolId == kProtocolId); } 1751 1752 /** 1753 * Returns the Protocol ID value. 1754 * 1755 * @returns the Protocol ID value. 1756 * 1757 */ GetProtocolId(void) const1758 uint8_t GetProtocolId(void) const { return mProtocolId; } 1759 1760 /** 1761 * Returns the Protocol Version value. 1762 * 1763 * @returns The Protocol Version value. 1764 * 1765 */ GetProtocolVersion(void) const1766 uint8_t GetProtocolVersion(void) const { return mFlags >> kVersionOffset; } 1767 1768 /** 1769 * Indicates whether or not the Native Commissioner flag is set. 1770 * 1771 * @retval TRUE If the Native Commissioner flag is set. 1772 * @retval FALSE If the Native Commissioner flag is not set. 1773 * 1774 */ IsNative(void) const1775 bool IsNative(void) const { return (mFlags & kNativeFlag) != 0; } 1776 1777 /** 1778 * Clears the Native Commissioner flag. 1779 * 1780 */ ClearNative(void)1781 void ClearNative(void) { mFlags &= ~kNativeFlag; } 1782 1783 /** 1784 * Sets the Native Commissioner flag. 1785 * 1786 */ SetNative(void)1787 void SetNative(void) { mFlags |= kNativeFlag; } 1788 1789 /** 1790 * Indicates whether or not the Joining Permitted flag is set. 1791 * 1792 * @retval TRUE If the Joining Permitted flag is set. 1793 * @retval FALSE If the Joining Permitted flag is not set. 1794 * 1795 */ IsJoiningPermitted(void) const1796 bool IsJoiningPermitted(void) const { return (mFlags & kJoiningFlag) != 0; } 1797 1798 /** 1799 * Clears the Joining Permitted flag. 1800 * 1801 */ ClearJoiningPermitted(void)1802 void ClearJoiningPermitted(void) { mFlags &= ~kJoiningFlag; } 1803 1804 /** 1805 * Sets the Joining Permitted flag. 1806 * 1807 */ SetJoiningPermitted(void)1808 void SetJoiningPermitted(void) 1809 { 1810 mFlags |= kJoiningFlag; 1811 1812 #if OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION != 2 // check against kProtocolVersion 1813 mFlags &= ~kVersionMask; 1814 mFlags |= OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION << kVersionOffset; 1815 #endif 1816 } 1817 1818 /** 1819 * Gets the Network Name field. 1820 * 1821 * @returns The Network Name field as `NameData`. 1822 * 1823 */ GetNetworkName(void) const1824 MeshCoP::NameData GetNetworkName(void) const { return MeshCoP::NameData(mNetworkName, sizeof(mNetworkName)); } 1825 1826 /** 1827 * Sets the Network Name field. 1828 * 1829 * @param[in] aNameData The Network Name (as a `NameData`). 1830 * 1831 */ SetNetworkName(const MeshCoP::NameData & aNameData)1832 void SetNetworkName(const MeshCoP::NameData &aNameData) { aNameData.CopyTo(mNetworkName, sizeof(mNetworkName)); } 1833 1834 /** 1835 * Returns the Extended PAN ID field. 1836 * 1837 * @returns The Extended PAN ID field. 1838 * 1839 */ GetExtendedPanId(void) const1840 const otExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; } 1841 1842 /** 1843 * Sets the Extended PAN ID field. 1844 * 1845 * @param[in] aExtPanId An Extended PAN ID. 1846 * 1847 */ SetExtendedPanId(const otExtendedPanId & aExtPanId)1848 void SetExtendedPanId(const otExtendedPanId &aExtPanId) { mExtendedPanId = aExtPanId; } 1849 1850 private: 1851 uint8_t mProtocolId; 1852 uint8_t mFlags; 1853 char mNetworkName[MeshCoP::NetworkName::kMaxSize]; 1854 otExtendedPanId mExtendedPanId; 1855 } OT_TOOL_PACKED_END; 1856 1857 /** 1858 * @} 1859 * 1860 */ 1861 1862 } // namespace Mac 1863 } // namespace ot 1864 1865 #endif // MAC_FRAME_HPP_ 1866