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_header_ie.hpp" 44 #include "mac/mac_types.hpp" 45 #include "meshcop/network_name.hpp" 46 47 namespace ot { 48 namespace Mac { 49 50 /** 51 * @addtogroup core-mac 52 * 53 * @{ 54 */ 55 56 /** 57 * Implements IEEE 802.15.4 MAC frame generation and parsing. 58 */ 59 class Frame : public otRadioFrame 60 { 61 public: 62 /** 63 * Represents the MAC frame type. 64 * 65 * Values match the Frame Type field in Frame Control Field (FCF) as an `uint16_t`. 66 */ 67 enum Type : uint16_t 68 { 69 kTypeBeacon = 0, ///< Beacon Frame Type. 70 kTypeData = 1, ///< Data Frame Type. 71 kTypeAck = 2, ///< Ack Frame Type. 72 kTypeMacCmd = 3, ///< MAC Command Frame Type. 73 kTypeMultipurpose = 5, ///< Multipurpose Frame Type. 74 }; 75 76 /** 77 * Represents the MAC frame version. 78 * 79 * Values match the Version field in Frame Control Field (FCF) as an `uint16_t`. 80 */ 81 enum Version : uint16_t 82 { 83 kVersion2003 = 0 << 12, ///< 2003 Frame Version. 84 kVersion2006 = 1 << 12, ///< 2006 Frame Version. 85 kVersion2015 = 2 << 12, ///< 2015 Frame Version. 86 }; 87 88 /** 89 * Represents the MAC frame security level. 90 * 91 * Values match the Security Level field in Security Control Field as an `uint8_t`. 92 */ 93 enum SecurityLevel : uint8_t 94 { 95 kSecurityNone = 0, ///< No security. 96 kSecurityMic32 = 1, ///< No encryption, MIC-32 authentication. 97 kSecurityMic64 = 2, ///< No encryption, MIC-64 authentication. 98 kSecurityMic128 = 3, ///< No encryption, MIC-128 authentication. 99 kSecurityEnc = 4, ///< Encryption, no authentication 100 kSecurityEncMic32 = 5, ///< Encryption with MIC-32 authentication. 101 kSecurityEncMic64 = 6, ///< Encryption with MIC-64 authentication. 102 kSecurityEncMic128 = 7, ///< Encryption with MIC-128 authentication. 103 }; 104 105 /** 106 * Represents the MAC frame security key identifier mode. 107 * 108 * Values match the Key Identifier Mode field in Security Control Field as an `uint8_t`. 109 */ 110 enum KeyIdMode : uint8_t 111 { 112 kKeyIdMode0 = 0 << 3, ///< Key ID Mode 0 - Key is determined implicitly. 113 kKeyIdMode1 = 1 << 3, ///< Key ID Mode 1 - Key is determined from Key Index field. 114 kKeyIdMode2 = 2 << 3, ///< Key ID Mode 2 - Key is determined from 4-bytes Key Source and Index fields. 115 kKeyIdMode3 = 3 << 3, ///< Key ID Mode 3 - Key is determined from 8-bytes Key Source and Index fields. 116 }; 117 118 /** 119 * Represents a subset of MAC Command Identifiers. 120 */ 121 enum CommandId : uint8_t 122 { 123 kMacCmdAssociationRequest = 1, 124 kMacCmdAssociationResponse = 2, 125 kMacCmdDisassociationNotification = 3, 126 kMacCmdDataRequest = 4, 127 kMacCmdPanidConflictNotification = 5, 128 kMacCmdOrphanNotification = 6, 129 kMacCmdBeaconRequest = 7, 130 kMacCmdCoordinatorRealignment = 8, 131 kMacCmdGtsRequest = 9, 132 }; 133 134 static constexpr uint16_t kInfoStringSize = 128; ///< Max chars for `InfoString` (ToInfoString()). 135 136 static constexpr uint8_t kPreambleSize = 4; 137 static constexpr uint8_t kSfdSize = 1; 138 static constexpr uint8_t kPhrSize = 1; 139 static constexpr uint8_t kPhyHeaderSize = kPreambleSize + kSfdSize + kPhrSize; 140 static constexpr uint8_t kFcfSize = sizeof(uint16_t); 141 static constexpr uint8_t kDsnSize = sizeof(uint8_t); 142 static constexpr uint8_t k154FcsSize = sizeof(uint16_t); 143 static constexpr uint8_t kImmAckLength = kFcfSize + kDsnSize + k154FcsSize; 144 145 /** 146 * Defines the fixed-length `String` object returned from `ToInfoString()` method. 147 */ 148 typedef String<kInfoStringSize> InfoString; 149 150 /** 151 * Indicates whether the frame is empty (no payload). 152 * 153 * @retval TRUE The frame is empty (no PSDU payload). 154 * @retval FALSE The frame is not empty. 155 */ IsEmpty(void) const156 bool IsEmpty(void) const { return (mLength == 0); } 157 158 /** 159 * Validates the frame. 160 * 161 * @retval kErrorNone Successfully parsed the MAC header. 162 * @retval kErrorParse Failed to parse through the MAC header. 163 */ 164 Error ValidatePsdu(void) const; 165 166 /** 167 * Returns the IEEE 802.15.4 Frame Type. 168 * 169 * @returns The IEEE 802.15.4 Frame Type. 170 */ GetType(void) const171 uint8_t GetType(void) const { return GetPsdu()[0] & kFcfFrameTypeMask; } 172 173 /** 174 * Returns whether the frame is an Ack frame. 175 * 176 * @retval TRUE If this is an Ack. 177 * @retval FALSE If this is not an Ack. 178 */ IsAck(void) const179 bool IsAck(void) const { return GetType() == kTypeAck; } 180 181 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 182 /** 183 * This method returns whether the frame is an IEEE 802.15.4 Wake-up frame. 184 * 185 * @retval TRUE If this is a Wake-up frame. 186 * @retval FALSE If this is not a Wake-up frame. 187 */ 188 bool IsWakeupFrame(void) const; 189 190 /** 191 * This method returns the Rendezvous Time IE of a wake-up frame. 192 * 193 * @returns Pointer to the Rendezvous Time IE. 194 */ GetRendezvousTimeIe(void)195 RendezvousTimeIe *GetRendezvousTimeIe(void) { return AsNonConst(AsConst(this)->GetRendezvousTimeIe()); } 196 197 /** 198 * This method returns the Rendezvous Time IE of a wake-up frame. 199 * 200 * @returns Const pointer to the Rendezvous Time IE. 201 */ GetRendezvousTimeIe(void) const202 const RendezvousTimeIe *GetRendezvousTimeIe(void) const 203 { 204 const uint8_t *ie = GetHeaderIe(RendezvousTimeIe::kHeaderIeId); 205 206 return (ie != nullptr) ? reinterpret_cast<const RendezvousTimeIe *>(ie + sizeof(HeaderIe)) : nullptr; 207 } 208 209 /** 210 * This method returns the Connection IE of a wake-up frame. 211 * 212 * @returns Pointer to the Connection IE. 213 */ GetConnectionIe(void)214 ConnectionIe *GetConnectionIe(void) { return AsNonConst(AsConst(this)->GetConnectionIe()); } 215 216 /** 217 * This method returns the Connection IE of a wake-up frame. 218 * 219 * @returns Const pointer to the Connection IE. 220 */ GetConnectionIe(void) const221 const ConnectionIe *GetConnectionIe(void) const 222 { 223 const uint8_t *ie = GetThreadIe(ConnectionIe::kThreadIeSubtype); 224 225 return (ie != nullptr) ? reinterpret_cast<const ConnectionIe *>(ie + sizeof(HeaderIe)) : nullptr; 226 } 227 #endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 228 229 /** 230 * Returns the IEEE 802.15.4 Frame Version. 231 * 232 * @returns The IEEE 802.15.4 Frame Version. 233 */ GetVersion(void) const234 uint16_t GetVersion(void) const { return GetFrameControlField() & kFcfFrameVersionMask; } 235 236 /** 237 * Returns if this IEEE 802.15.4 frame's version is 2015. 238 * 239 * @returns TRUE if version is 2015, FALSE otherwise. 240 */ IsVersion2015(void) const241 bool IsVersion2015(void) const { return IsVersion2015(GetFrameControlField()); } 242 243 /** 244 * Indicates whether or not security is enabled. 245 * 246 * @retval TRUE If security is enabled. 247 * @retval FALSE If security is not enabled. 248 */ GetSecurityEnabled(void) const249 bool GetSecurityEnabled(void) const { return IsSecurityEnabled(GetFrameControlField()); } 250 251 /** 252 * Indicates whether or not the Frame Pending bit is set. 253 * 254 * @retval TRUE If the Frame Pending bit is set. 255 * @retval FALSE If the Frame Pending bit is not set. 256 */ GetFramePending(void) const257 bool GetFramePending(void) const { return IsFramePending(GetFrameControlField()); } 258 259 /** 260 * Sets the Frame Pending bit. 261 * 262 * @note This method must not be called on a Multipurpose frame with short Frame Control field. 263 * 264 * @param[in] aFramePending The Frame Pending bit. 265 */ 266 void SetFramePending(bool aFramePending); 267 268 /** 269 * Indicates whether or not the Ack Request bit is set. 270 * 271 * @retval TRUE If the Ack Request bit is set. 272 * @retval FALSE If the Ack Request bit is not set. 273 */ GetAckRequest(void) const274 bool GetAckRequest(void) const { return IsAckRequest(GetFrameControlField()); } 275 276 /** 277 * Sets the Ack Request bit. 278 * 279 * @note This method must not be called on a Multipurpose frame with short Frame Control field. 280 * 281 * @param[in] aAckRequest The Ack Request bit. 282 */ 283 void SetAckRequest(bool aAckRequest); 284 285 /** 286 * Indicates whether or not the PanId Compression bit is set. 287 * 288 * @note This method must not be called on a Multipurpose frame, which lacks this flag. 289 * 290 * @retval TRUE If the PanId Compression bit is set. 291 * @retval FALSE If the PanId Compression bit is not set. 292 */ IsPanIdCompressed(void) const293 bool IsPanIdCompressed(void) const { return (GetFrameControlField() & kFcfPanidCompression) != 0; } 294 295 /** 296 * Indicates whether or not IEs present. 297 * 298 * @retval TRUE If IEs present. 299 * @retval FALSE If no IE present. 300 */ IsIePresent(void) const301 bool IsIePresent(void) const { return IsIePresent(GetFrameControlField()); } 302 303 /** 304 * Sets the IE Present bit. 305 * 306 * @note This method must not be called on a Multipurpose frame with short Frame Control field. 307 * 308 * @param[in] aIePresent The IE Present bit. 309 */ 310 void SetIePresent(bool aIePresent); 311 312 /** 313 * Returns the Sequence Number value. 314 * 315 * @returns The Sequence Number value. 316 */ 317 uint8_t GetSequence(void) const; 318 319 /** 320 * Sets the Sequence Number value. 321 * 322 * @param[in] aSequence The Sequence Number value. 323 */ 324 void SetSequence(uint8_t aSequence); 325 326 /** 327 * Indicates whether or not the Sequence Number is present. 328 * 329 * @returns TRUE if the Sequence Number is present, FALSE otherwise. 330 */ IsSequencePresent(void) const331 uint8_t IsSequencePresent(void) const { return IsSequencePresent(GetFrameControlField()); } 332 333 /** 334 * Indicates whether or not the Destination PAN ID is present. 335 * 336 * @returns TRUE if the Destination PAN ID is present, FALSE otherwise. 337 */ IsDstPanIdPresent(void) const338 bool IsDstPanIdPresent(void) const { return IsDstPanIdPresent(GetFrameControlField()); } 339 340 /** 341 * Gets the Destination PAN Identifier. 342 * 343 * @param[out] aPanId The Destination PAN Identifier. 344 * 345 * @retval kErrorNone Successfully retrieved the Destination PAN Identifier. 346 * @retval kErrorParse Failed to parse the PAN Identifier. 347 */ 348 Error GetDstPanId(PanId &aPanId) const; 349 350 /** 351 * Indicates whether or not the Destination Address is present for this object. 352 * 353 * @retval TRUE If the Destination Address is present. 354 * @retval FALSE If the Destination Address is not present. 355 */ IsDstAddrPresent() const356 bool IsDstAddrPresent() const { return IsDstAddrPresent(GetFrameControlField()); } 357 358 /** 359 * Gets the Destination Address. 360 * 361 * @param[out] aAddress The Destination Address. 362 * 363 * @retval kErrorNone Successfully retrieved the Destination Address. 364 */ 365 Error GetDstAddr(Address &aAddress) const; 366 367 /** 368 * Indicates whether or not the Source Address is present for this object. 369 * 370 * @retval TRUE If the Source Address is present. 371 * @retval FALSE If the Source Address is not present. 372 */ IsSrcPanIdPresent(void) const373 bool IsSrcPanIdPresent(void) const { return IsSrcPanIdPresent(GetFrameControlField()); } 374 375 /** 376 * Gets the Source PAN Identifier. 377 * 378 * @param[out] aPanId The Source PAN Identifier. 379 * 380 * @retval kErrorNone Successfully retrieved the Source PAN Identifier. 381 */ 382 Error GetSrcPanId(PanId &aPanId) const; 383 384 /** 385 * Indicates whether or not the Source Address is present for this object. 386 * 387 * @retval TRUE If the Source Address is present. 388 * @retval FALSE If the Source Address is not present. 389 */ IsSrcAddrPresent(void) const390 bool IsSrcAddrPresent(void) const { return IsSrcAddrPresent(GetFrameControlField()); } 391 392 /** 393 * Gets the Source Address. 394 * 395 * @param[out] aAddress The Source Address. 396 * 397 * @retval kErrorNone Successfully retrieved the Source Address. 398 */ 399 Error GetSrcAddr(Address &aAddress) const; 400 401 /** 402 * Gets the Security Control Field. 403 * 404 * @param[out] aSecurityControlField The Security Control Field. 405 * 406 * @retval kErrorNone Successfully retrieved the Security Level Identifier. 407 * @retval kErrorParse Failed to find the security control field in the frame. 408 */ 409 Error GetSecurityControlField(uint8_t &aSecurityControlField) const; 410 411 /** 412 * Gets the Security Level Identifier. 413 * 414 * @param[out] aSecurityLevel The Security Level Identifier. 415 * 416 * @retval kErrorNone Successfully retrieved the Security Level Identifier. 417 */ 418 Error GetSecurityLevel(uint8_t &aSecurityLevel) const; 419 420 /** 421 * Gets the Key Identifier Mode. 422 * 423 * @param[out] aKeyIdMode The Key Identifier Mode. 424 * 425 * @retval kErrorNone Successfully retrieved the Key Identifier Mode. 426 */ 427 Error GetKeyIdMode(uint8_t &aKeyIdMode) const; 428 429 /** 430 * Gets the Frame Counter. 431 * 432 * @param[out] aFrameCounter The Frame Counter. 433 * 434 * @retval kErrorNone Successfully retrieved the Frame Counter. 435 */ 436 Error GetFrameCounter(uint32_t &aFrameCounter) const; 437 438 /** 439 * Sets the Frame Counter. 440 * 441 * @param[in] aFrameCounter The Frame Counter. 442 */ 443 void SetFrameCounter(uint32_t aFrameCounter); 444 445 /** 446 * Returns a pointer to the Key Source. 447 * 448 * @returns A pointer to the Key Source. 449 */ 450 const uint8_t *GetKeySource(void) const; 451 452 /** 453 * Sets the Key Source. 454 * 455 * @param[in] aKeySource A pointer to the Key Source value. 456 */ 457 void SetKeySource(const uint8_t *aKeySource); 458 459 /** 460 * Gets the Key Identifier. 461 * 462 * @param[out] aKeyId The Key Identifier. 463 * 464 * @retval kErrorNone Successfully retrieved the Key Identifier. 465 */ 466 Error GetKeyId(uint8_t &aKeyId) const; 467 468 /** 469 * Sets the Key Identifier. 470 * 471 * @param[in] aKeyId The Key Identifier. 472 */ 473 void SetKeyId(uint8_t aKeyId); 474 475 /** 476 * Gets the Command ID. 477 * 478 * @param[out] aCommandId The Command ID. 479 * 480 * @retval kErrorNone Successfully retrieved the Command ID. 481 */ 482 Error GetCommandId(uint8_t &aCommandId) const; 483 484 /** 485 * Indicates whether the frame is a MAC Data Request command (data poll). 486 * 487 * For 802.15.4-2015 and above frame, the frame should be already decrypted. 488 * 489 * @returns TRUE if frame is a MAC Data Request command, FALSE otherwise. 490 */ 491 bool IsDataRequestCommand(void) const; 492 493 /** 494 * Returns the MAC Frame Length, namely the IEEE 802.15.4 PSDU length. 495 * 496 * @returns The MAC Frame Length. 497 */ GetLength(void) const498 uint16_t GetLength(void) const { return mLength; } 499 500 /** 501 * Sets the MAC Frame Length. 502 * 503 * @param[in] aLength The MAC Frame Length. 504 */ SetLength(uint16_t aLength)505 void SetLength(uint16_t aLength) { mLength = aLength; } 506 507 /** 508 * Returns the MAC header size. 509 * 510 * @returns The MAC header size. 511 */ 512 uint8_t GetHeaderLength(void) const; 513 514 /** 515 * Returns the MAC footer size. 516 * 517 * @returns The MAC footer size. 518 */ 519 uint8_t GetFooterLength(void) const; 520 521 /** 522 * Returns the current MAC Payload length. 523 * 524 * @returns The current MAC Payload length. 525 */ 526 uint16_t GetPayloadLength(void) const; 527 528 /** 529 * Returns the maximum MAC Payload length for the given MAC header and footer. 530 * 531 * @returns The maximum MAC Payload length for the given MAC header and footer. 532 */ 533 uint16_t GetMaxPayloadLength(void) const; 534 535 /** 536 * Sets the MAC Payload length. 537 */ 538 void SetPayloadLength(uint16_t aLength); 539 540 /** 541 * Returns the IEEE 802.15.4 channel used for transmission or reception. 542 * 543 * @returns The IEEE 802.15.4 channel used for transmission or reception. 544 */ GetChannel(void) const545 uint8_t GetChannel(void) const { return mChannel; } 546 547 /** 548 * Returns a pointer to the PSDU. 549 * 550 * @returns A pointer to the PSDU. 551 */ GetPsdu(void)552 uint8_t *GetPsdu(void) { return mPsdu; } 553 554 /** 555 * Returns a pointer to the PSDU. 556 * 557 * @returns A pointer to the PSDU. 558 */ GetPsdu(void) const559 const uint8_t *GetPsdu(void) const { return mPsdu; } 560 561 /** 562 * Returns a pointer to the MAC Header. 563 * 564 * @returns A pointer to the MAC Header. 565 */ GetHeader(void)566 uint8_t *GetHeader(void) { return GetPsdu(); } 567 568 /** 569 * Returns a pointer to the MAC Header. 570 * 571 * @returns A pointer to the MAC Header. 572 */ GetHeader(void) const573 const uint8_t *GetHeader(void) const { return GetPsdu(); } 574 575 /** 576 * Returns a pointer to the MAC Payload. 577 * 578 * @returns A pointer to the MAC Payload. 579 */ GetPayload(void)580 uint8_t *GetPayload(void) { return AsNonConst(AsConst(this)->GetPayload()); } 581 582 /** 583 * Returns a pointer to the MAC Payload. 584 * 585 * @returns A pointer to the MAC Payload. 586 */ 587 const uint8_t *GetPayload(void) const; 588 589 /** 590 * Returns a pointer to the MAC Footer. 591 * 592 * @returns A pointer to the MAC Footer. 593 */ GetFooter(void)594 uint8_t *GetFooter(void) { return AsNonConst(AsConst(this)->GetFooter()); } 595 596 /** 597 * Returns a pointer to the MAC Footer. 598 * 599 * @returns A pointer to the MAC Footer. 600 */ 601 const uint8_t *GetFooter(void) const; 602 603 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 604 605 /** 606 * Returns a pointer to the vendor specific Time IE. 607 * 608 * @returns A pointer to the Time IE, `nullptr` if not found. 609 */ GetTimeIe(void)610 TimeIe *GetTimeIe(void) { return AsNonConst(AsConst(this)->GetTimeIe()); } 611 612 /** 613 * Returns a pointer to the vendor specific Time IE. 614 * 615 * @returns A pointer to the Time IE, `nullptr` if not found. 616 */ 617 const TimeIe *GetTimeIe(void) const; 618 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 619 620 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 621 /** 622 * Returns a pointer to the Header IE. 623 * 624 * @param[in] aIeId The Element Id of the Header IE. 625 * 626 * @returns A pointer to the Header IE, `nullptr` if not found. 627 */ GetHeaderIe(uint8_t aIeId)628 uint8_t *GetHeaderIe(uint8_t aIeId) { return AsNonConst(AsConst(this)->GetHeaderIe(aIeId)); } 629 630 /** 631 * Returns a pointer to the Header IE. 632 * 633 * @param[in] aIeId The Element Id of the Header IE. 634 * 635 * @returns A pointer to the Header IE, `nullptr` if not found. 636 */ 637 const uint8_t *GetHeaderIe(uint8_t aIeId) const; 638 639 /** 640 * Returns a pointer to a specific Thread IE. 641 * 642 * A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`. 643 * 644 * @param[in] aSubType The sub type of the Thread IE. 645 * 646 * @returns A pointer to the Thread IE, `nullptr` if not found. 647 */ GetThreadIe(uint8_t aSubType)648 uint8_t *GetThreadIe(uint8_t aSubType) { return AsNonConst(AsConst(this)->GetThreadIe(aSubType)); } 649 650 /** 651 * Returns a pointer to a specific Thread IE. 652 * 653 * A Thread IE is a vendor specific IE with Vendor OUI as `kVendorOuiThreadCompanyId`. 654 * 655 * @param[in] aSubType The sub type of the Thread IE. 656 * 657 * @returns A pointer to the Thread IE, `nullptr` if not found. 658 */ 659 const uint8_t *GetThreadIe(uint8_t aSubType) const; 660 661 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 662 /** 663 * Finds CSL IE in the frame and modify its content. 664 * 665 * @param[in] aCslPeriod CSL Period in CSL IE. 666 * @param[in] aCslPhase CSL Phase in CSL IE. 667 */ 668 void SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase); 669 670 /** 671 * Indicates whether or not the frame contains CSL IE. 672 * 673 * @retval TRUE If the frame contains CSL IE. 674 * @retval FALSE If the frame doesn't contain CSL IE. 675 */ 676 bool HasCslIe(void) const; 677 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 678 679 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 680 /** 681 * Returns a pointer to a CSL IE. 682 * 683 * @returns A pointer to the CSL IE, `nullptr` if not found. 684 */ 685 const CslIe *GetCslIe(void) const; 686 687 /** 688 * Returns a pointer to a CSL IE. 689 * 690 * @returns A pointer to the CSL IE, `nullptr` if not found. 691 */ GetCslIe(void)692 CslIe *GetCslIe(void) { return AsNonConst(AsConst(this)->GetCslIe()); } 693 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 694 695 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 696 /** 697 * Finds Enhanced ACK Probing (Vendor Specific) IE and set its value. 698 * 699 * @param[in] aValue A pointer to the value to set. 700 * @param[in] aLen The length of @p aValue. 701 */ 702 void SetEnhAckProbingIe(const uint8_t *aValue, uint8_t aLen); 703 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 704 705 #endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 706 707 #if OPENTHREAD_CONFIG_MULTI_RADIO 708 /** 709 * Gets the radio link type of the frame. 710 * 711 * @returns Frame's radio link type. 712 */ GetRadioType(void) const713 RadioType GetRadioType(void) const { return static_cast<RadioType>(mRadioType); } 714 715 /** 716 * Sets the radio link type of the frame. 717 * 718 * @param[in] aRadioType A radio link type. 719 */ SetRadioType(RadioType aRadioType)720 void SetRadioType(RadioType aRadioType) { mRadioType = static_cast<uint8_t>(aRadioType); } 721 #endif 722 723 /** 724 * Returns the maximum transmission unit size (MTU). 725 * 726 * @returns The maximum transmission unit (MTU). 727 */ GetMtu(void) const728 uint16_t GetMtu(void) const 729 #if !OPENTHREAD_CONFIG_MULTI_RADIO && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE 730 { 731 return OT_RADIO_FRAME_MAX_SIZE; 732 } 733 #else 734 ; 735 #endif 736 737 /** 738 * Returns the FCS size. 739 * 740 * @returns This method returns the FCS size. 741 */ GetFcsSize(void) const742 uint8_t GetFcsSize(void) const 743 #if !OPENTHREAD_CONFIG_MULTI_RADIO && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE 744 { 745 return k154FcsSize; 746 } 747 #else 748 ; 749 #endif 750 751 /** 752 * Returns information about the frame object as an `InfoString` object. 753 * 754 * @returns An `InfoString` containing info about the frame. 755 */ 756 InfoString ToInfoString(void) const; 757 758 /** 759 * Returns the Frame Control field of the frame. 760 * 761 * @returns The Frame Control field. 762 */ GetFrameControlField(void) const763 uint16_t GetFrameControlField(void) const 764 { 765 uint16_t fcf = mPsdu[0]; 766 767 #if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME 768 if (!IsShortFcf(fcf)) 769 #endif 770 { 771 fcf |= (mPsdu[1] << 8); 772 } 773 774 return fcf; 775 } 776 777 protected: 778 static constexpr uint8_t kShortFcfSize = sizeof(uint8_t); 779 static constexpr uint8_t kSecurityControlSize = sizeof(uint8_t); 780 static constexpr uint8_t kFrameCounterSize = sizeof(uint32_t); 781 static constexpr uint8_t kCommandIdSize = sizeof(uint8_t); 782 static constexpr uint8_t kKeyIndexSize = sizeof(uint8_t); 783 784 static constexpr uint16_t kFcfFrameTypeMask = 7 << 0; 785 786 static constexpr uint16_t kFcfAddrNone = 0; 787 static constexpr uint16_t kFcfAddrShort = 2; 788 static constexpr uint16_t kFcfAddrExt = 3; 789 static constexpr uint16_t kFcfAddrMask = 3; 790 791 // Frame Control field format for general MAC frame 792 static constexpr uint16_t kFcfSecurityEnabled = 1 << 3; 793 static constexpr uint16_t kFcfFramePending = 1 << 4; 794 static constexpr uint16_t kFcfAckRequest = 1 << 5; 795 static constexpr uint16_t kFcfPanidCompression = 1 << 6; 796 static constexpr uint16_t kFcfSequenceSuppression = 1 << 8; 797 static constexpr uint16_t kFcfIePresent = 1 << 9; 798 static constexpr uint16_t kFcfDstAddrShift = 10; 799 static constexpr uint16_t kFcfDstAddrNone = kFcfAddrNone << kFcfDstAddrShift; 800 static constexpr uint16_t kFcfDstAddrShort = kFcfAddrShort << kFcfDstAddrShift; 801 static constexpr uint16_t kFcfDstAddrExt = kFcfAddrExt << kFcfDstAddrShift; 802 static constexpr uint16_t kFcfDstAddrMask = kFcfAddrMask << kFcfDstAddrShift; 803 static constexpr uint16_t kFcfFrameVersionMask = 3 << 12; 804 static constexpr uint16_t kFcfSrcAddrShift = 14; 805 static constexpr uint16_t kFcfSrcAddrNone = kFcfAddrNone << kFcfSrcAddrShift; 806 static constexpr uint16_t kFcfSrcAddrShort = kFcfAddrShort << kFcfSrcAddrShift; 807 static constexpr uint16_t kFcfSrcAddrExt = kFcfAddrExt << kFcfSrcAddrShift; 808 static constexpr uint16_t kFcfSrcAddrMask = kFcfAddrMask << kFcfSrcAddrShift; 809 810 // Frame Control field format for MAC Multipurpose frame 811 static constexpr uint16_t kMpFcfLongFrame = 1 << 3; 812 static constexpr uint16_t kMpFcfDstAddrShift = 4; 813 static constexpr uint16_t kMpFcfDstAddrNone = kFcfAddrNone << kMpFcfDstAddrShift; 814 static constexpr uint16_t kMpFcfDstAddrShort = kFcfAddrShort << kMpFcfDstAddrShift; 815 static constexpr uint16_t kMpFcfDstAddrExt = kFcfAddrExt << kMpFcfDstAddrShift; 816 static constexpr uint16_t kMpFcfDstAddrMask = kFcfAddrMask << kMpFcfDstAddrShift; 817 static constexpr uint16_t kMpFcfSrcAddrShift = 6; 818 static constexpr uint16_t kMpFcfSrcAddrNone = kFcfAddrNone << kMpFcfSrcAddrShift; 819 static constexpr uint16_t kMpFcfSrcAddrShort = kFcfAddrShort << kMpFcfSrcAddrShift; 820 static constexpr uint16_t kMpFcfSrcAddrExt = kFcfAddrExt << kMpFcfSrcAddrShift; 821 static constexpr uint16_t kMpFcfSrcAddrMask = kFcfAddrMask << kMpFcfSrcAddrShift; 822 static constexpr uint16_t kMpFcfPanidPresent = 1 << 8; 823 static constexpr uint16_t kMpFcfSecurityEnabled = 1 << 9; 824 static constexpr uint16_t kMpFcfSequenceSuppression = 1 << 10; 825 static constexpr uint16_t kMpFcfFramePending = 1 << 11; 826 static constexpr uint16_t kMpFcfAckRequest = 1 << 14; 827 static constexpr uint16_t kMpFcfIePresent = 1 << 15; 828 829 static constexpr uint8_t kSecLevelMask = 7 << 0; 830 static constexpr uint8_t kKeyIdModeMask = 3 << 3; 831 832 static constexpr uint8_t kMic0Size = 0; 833 static constexpr uint8_t kMic32Size = 32 / kBitsPerByte; 834 static constexpr uint8_t kMic64Size = 64 / kBitsPerByte; 835 static constexpr uint8_t kMic128Size = 128 / kBitsPerByte; 836 static constexpr uint8_t kMaxMicSize = kMic128Size; 837 838 static constexpr uint8_t kKeySourceSizeMode0 = 0; 839 static constexpr uint8_t kKeySourceSizeMode1 = 0; 840 static constexpr uint8_t kKeySourceSizeMode2 = 4; 841 static constexpr uint8_t kKeySourceSizeMode3 = 8; 842 843 static constexpr uint8_t kInvalidIndex = 0xff; 844 static constexpr uint8_t kInvalidSize = kInvalidIndex; 845 static constexpr uint8_t kMaxPsduSize = kInvalidSize - 1; 846 847 void SetFrameControlField(uint16_t aFcf); 848 uint8_t SkipSequenceIndex(void) const; 849 uint8_t FindDstPanIdIndex(void) const; 850 uint8_t FindDstAddrIndex(void) const; 851 uint8_t FindSrcPanIdIndex(void) const; 852 uint8_t FindSrcAddrIndex(void) const; 853 uint8_t SkipAddrFieldIndex(void) const; 854 uint8_t FindSecurityHeaderIndex(void) const; 855 uint8_t SkipSecurityHeaderIndex(void) const; 856 uint8_t FindPayloadIndex(void) const; 857 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 858 uint8_t FindHeaderIeIndex(void) const; 859 #endif 860 861 #if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME GetFcfSize(uint16_t aFcf)862 static uint8_t GetFcfSize(uint16_t aFcf) { return IsShortFcf(aFcf) ? kShortFcfSize : kFcfSize; } 863 #else 864 // clang-format off GetFcfSize(uint16_t)865 static uint8_t GetFcfSize(uint16_t /* aFcf */) { return kFcfSize; } 866 // clang-format on 867 #endif 868 869 #if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME Select(uint16_t aFcf)870 template <uint16_t kValue, uint16_t kMpValue> static uint16_t Select(uint16_t aFcf) 871 { 872 return IsMultipurpose(aFcf) ? kMpValue : kValue; 873 } 874 #else Select(uint16_t)875 template <uint16_t kValue, uint16_t kMpValue> static uint16_t Select(uint16_t /* aFcf */) { return kValue; } 876 #endif 877 MaskFcf(uint16_t aFcf)878 template <uint16_t kValue, uint16_t kMpValue> static uint16_t MaskFcf(uint16_t aFcf) 879 { 880 return aFcf & Select<kValue, kMpValue>(aFcf); 881 } 882 GetFcfDstAddr(uint16_t aFcf)883 static uint16_t GetFcfDstAddr(uint16_t aFcf) 884 { 885 return MaskFcf<kFcfDstAddrMask, kMpFcfDstAddrMask>(aFcf) >> Select<kFcfDstAddrShift, kMpFcfDstAddrShift>(aFcf); 886 } 887 GetFcfSrcAddr(uint16_t aFcf)888 static uint16_t GetFcfSrcAddr(uint16_t aFcf) 889 { 890 return MaskFcf<kFcfSrcAddrMask, kMpFcfSrcAddrMask>(aFcf) >> Select<kFcfSrcAddrShift, kMpFcfSrcAddrShift>(aFcf); 891 } 892 IsMultipurpose(uint16_t aFcf)893 static bool IsMultipurpose(uint16_t aFcf) { return (aFcf & kFcfFrameTypeMask) == kTypeMultipurpose; } IsShortFcf(uint16_t aFcf)894 static bool IsShortFcf(uint16_t aFcf) 895 { 896 return (aFcf & (kFcfFrameTypeMask | kMpFcfLongFrame)) == (kTypeMultipurpose | 0); 897 } IsSequencePresent(uint16_t aFcf)898 static bool IsSequencePresent(uint16_t aFcf) 899 { 900 return !MaskFcf<kFcfSequenceSuppression, kMpFcfSequenceSuppression>(aFcf); 901 } IsDstAddrPresent(uint16_t aFcf)902 static bool IsDstAddrPresent(uint16_t aFcf) { return MaskFcf<kFcfDstAddrMask, kMpFcfDstAddrMask>(aFcf); } 903 static bool IsDstPanIdPresent(uint16_t aFcf); IsSrcAddrPresent(uint16_t aFcf)904 static bool IsSrcAddrPresent(uint16_t aFcf) { return MaskFcf<kFcfSrcAddrMask, kMpFcfSrcAddrMask>(aFcf); } 905 static bool IsSrcPanIdPresent(uint16_t aFcf); IsSecurityEnabled(uint16_t aFcf)906 static bool IsSecurityEnabled(uint16_t aFcf) { return MaskFcf<kFcfSecurityEnabled, kMpFcfSecurityEnabled>(aFcf); } IsFramePending(uint16_t aFcf)907 static bool IsFramePending(uint16_t aFcf) { return MaskFcf<kFcfFramePending, kMpFcfFramePending>(aFcf); } IsIePresent(uint16_t aFcf)908 static bool IsIePresent(uint16_t aFcf) { return MaskFcf<kFcfIePresent, kMpFcfIePresent>(aFcf); } IsAckRequest(uint16_t aFcf)909 static bool IsAckRequest(uint16_t aFcf) { return MaskFcf<kFcfAckRequest, kMpFcfAckRequest>(aFcf); } IsVersion2015(uint16_t aFcf)910 static bool IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kVersion2015; } 911 912 static uint16_t DetermineFcfAddrType(const Address &aAddress, uint16_t aBitShift); 913 914 static uint8_t CalculateAddrFieldSize(uint16_t aFcf); 915 static uint8_t CalculateSecurityHeaderSize(uint8_t aSecurityControl); 916 static uint8_t CalculateKeySourceSize(uint8_t aSecurityControl); 917 static uint8_t CalculateMicSize(uint8_t aSecurityControl); 918 }; 919 920 /** 921 * Supports received IEEE 802.15.4 MAC frame processing. 922 */ 923 class RxFrame : public Frame 924 { 925 public: 926 friend class TxFrame; 927 928 /** 929 * Returns the RSSI in dBm used for reception. 930 * 931 * @returns The RSSI in dBm used for reception. 932 */ GetRssi(void) const933 int8_t GetRssi(void) const { return mInfo.mRxInfo.mRssi; } 934 935 /** 936 * Sets the RSSI in dBm used for reception. 937 * 938 * @param[in] aRssi The RSSI in dBm used for reception. 939 */ SetRssi(int8_t aRssi)940 void SetRssi(int8_t aRssi) { mInfo.mRxInfo.mRssi = aRssi; } 941 942 /** 943 * Returns the receive Link Quality Indicator. 944 * 945 * @returns The receive Link Quality Indicator. 946 */ GetLqi(void) const947 uint8_t GetLqi(void) const { return mInfo.mRxInfo.mLqi; } 948 949 /** 950 * Sets the receive Link Quality Indicator. 951 * 952 * @param[in] aLqi The receive Link Quality Indicator. 953 */ SetLqi(uint8_t aLqi)954 void SetLqi(uint8_t aLqi) { mInfo.mRxInfo.mLqi = aLqi; } 955 956 /** 957 * Indicates whether or not the received frame is acknowledged with frame pending set. 958 * 959 * @retval TRUE This frame is acknowledged with frame pending set. 960 * @retval FALSE This frame is acknowledged with frame pending not set. 961 */ IsAckedWithFramePending(void) const962 bool IsAckedWithFramePending(void) const { return mInfo.mRxInfo.mAckedWithFramePending; } 963 964 /** 965 * Returns the timestamp when the frame was received. 966 * 967 * The value SHALL be the time of the local radio clock in 968 * microseconds when the end of the SFD (or equivalently: the start 969 * of the first symbol of the PHR) was present at the local antenna, 970 * see the definition of a "symbol boundary" in IEEE 802.15.4-2020, 971 * section 6.5.2 or equivalently the RMARKER definition in section 972 * 6.9.1 (albeit both unrelated to OT). 973 * 974 * The time is relative to the local radio clock as defined by 975 * `Radio::GetNow()`. 976 * 977 * @returns The timestamp in microseconds. 978 */ GetTimestamp(void) const979 const uint64_t &GetTimestamp(void) const { return mInfo.mRxInfo.mTimestamp; } 980 981 /** 982 * Performs AES CCM on the frame which is received. 983 * 984 * @param[in] aExtAddress A reference to the extended address, which will be used to generate nonce 985 * for AES CCM computation. 986 * @param[in] aMacKey A reference to the MAC key to decrypt the received frame. 987 * 988 * @retval kErrorNone Process of received frame AES CCM succeeded. 989 * @retval kErrorSecurity Received frame MIC check failed. 990 */ 991 Error ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const KeyMaterial &aMacKey); 992 993 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 994 /** 995 * Gets the offset to network time. 996 * 997 * @returns The offset to network time. 998 */ ComputeNetworkTimeOffset(void) const999 int64_t ComputeNetworkTimeOffset(void) const 1000 { 1001 return static_cast<int64_t>(GetTimeIe()->GetTime() - GetTimestamp()); 1002 } 1003 1004 /** 1005 * Gets the time sync sequence. 1006 * 1007 * @returns The time sync sequence. 1008 */ ReadTimeSyncSeq(void) const1009 uint8_t ReadTimeSyncSeq(void) const { return GetTimeIe()->GetSequence(); } 1010 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1011 }; 1012 1013 /** 1014 * Supports IEEE 802.15.4 MAC frame generation for transmission. 1015 */ 1016 class TxFrame : public Frame 1017 { 1018 public: 1019 /** 1020 * Represents header information. 1021 */ 1022 struct Info : public Clearable<Info> 1023 { 1024 /** 1025 * Initializes the `Info` by clearing all its fields (setting all bytes to zero). 1026 */ Infoot::Mac::TxFrame::Info1027 Info(void) { Clear(); } 1028 1029 /** 1030 * Prepares MAC headers based on `Info` fields in a given `TxFrame`. 1031 * 1032 * This method uses the `Info` structure to construct the MAC address and security headers in @p aTxFrame. 1033 * It determines the Frame Control Field (FCF), including setting the appropriate frame type, security level, 1034 * and addressing mode flags. It populates the source and destination addresses and PAN IDs within the MAC 1035 * header based on the information provided in the `Info` structure. 1036 * 1037 * It sets the Ack Request bit in the FCF if the following criteria are met: 1038 * - A destination address is present 1039 * - The destination address is not the broadcast address 1040 * - The frame type is not an ACK frame 1041 * 1042 * The header IE entries are prepared based on `mAppendTimeIe` and `mAppendCslIe` flags and the IE Present 1043 * flag in FCF is determined accordingly. 1044 * 1045 * The Frame Pending flag in FCF is not set. It may need to be set separately depending on the specific 1046 * requirements of the frame being transmitted. 1047 * 1048 * @param[in,out] aTxFrame The `TxFrame` instance in which to prepare and append the MAC headers. 1049 */ 1050 void PrepareHeadersIn(TxFrame &aTxFrame) const; 1051 1052 Type mType; ///< Frame type. 1053 Version mVersion; ///< Frame version. 1054 Addresses mAddrs; ///< Frame source and destination addresses. 1055 PanIds mPanIds; ///< Source and destination PAN Ids. 1056 SecurityLevel mSecurityLevel; ///< Frame security level. 1057 KeyIdMode mKeyIdMode; ///< Frame security key ID mode. 1058 CommandId mCommandId; ///< Command ID (applicable when `mType == kTypeMacCmd`). 1059 bool mSuppressSequence : 1; ///< Whether to suppress seq number. 1060 1061 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 1062 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1063 bool mAppendTimeIe : 1; ///< Whether to append Time IE. 1064 #endif 1065 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 1066 bool mAppendCslIe : 1; ///< Whether to append CSL IE. 1067 #endif 1068 bool mEmptyPayload : 1; ///< Whether payload is empty (to decide about appending Termination2 IE). 1069 #endif 1070 }; 1071 1072 /** 1073 * Sets the channel on which to send the frame. 1074 * 1075 * It also sets the `RxChannelAfterTxDone` to the same channel. 1076 * 1077 * @param[in] aChannel The channel used for transmission. 1078 */ SetChannel(uint8_t aChannel)1079 void SetChannel(uint8_t aChannel) 1080 { 1081 mChannel = aChannel; 1082 SetRxChannelAfterTxDone(aChannel); 1083 } 1084 1085 /** 1086 * Sets TX power to send the frame. 1087 * 1088 * @param[in] aTxPower The tx power used for transmission. 1089 */ SetTxPower(int8_t aTxPower)1090 void SetTxPower(int8_t aTxPower) { mInfo.mTxInfo.mTxPower = aTxPower; } 1091 1092 /** 1093 * Gets the RX channel after frame TX is done. 1094 * 1095 * @returns The RX channel after frame TX is done. 1096 */ GetRxChannelAfterTxDone(void) const1097 uint8_t GetRxChannelAfterTxDone(void) const { return mInfo.mTxInfo.mRxChannelAfterTxDone; } 1098 1099 /** 1100 * Sets the RX channel after frame TX is done. 1101 * 1102 * @param[in] aChannel The RX channel after frame TX is done. 1103 */ SetRxChannelAfterTxDone(uint8_t aChannel)1104 void SetRxChannelAfterTxDone(uint8_t aChannel) { mInfo.mTxInfo.mRxChannelAfterTxDone = aChannel; } 1105 1106 /** 1107 * Returns the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel 1108 * access failure. 1109 * 1110 * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006. 1111 * 1112 * @returns The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access 1113 * failure. 1114 */ GetMaxCsmaBackoffs(void) const1115 uint8_t GetMaxCsmaBackoffs(void) const { return mInfo.mTxInfo.mMaxCsmaBackoffs; } 1116 1117 /** 1118 * Sets the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel 1119 * access failure. 1120 * 1121 * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006. 1122 * 1123 * @param[in] aMaxCsmaBackoffs The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring 1124 * a channel access failure. 1125 */ SetMaxCsmaBackoffs(uint8_t aMaxCsmaBackoffs)1126 void SetMaxCsmaBackoffs(uint8_t aMaxCsmaBackoffs) { mInfo.mTxInfo.mMaxCsmaBackoffs = aMaxCsmaBackoffs; } 1127 1128 /** 1129 * Returns the maximum number of retries allowed after a transmission failure. 1130 * 1131 * Equivalent to macMaxFrameRetries in IEEE 802.15.4-2006. 1132 * 1133 * @returns The maximum number of retries allowed after a transmission failure. 1134 */ GetMaxFrameRetries(void) const1135 uint8_t GetMaxFrameRetries(void) const { return mInfo.mTxInfo.mMaxFrameRetries; } 1136 1137 /** 1138 * Sets the maximum number of retries allowed after a transmission failure. 1139 * 1140 * Equivalent to macMaxFrameRetries in IEEE 802.15.4-2006. 1141 * 1142 * @param[in] aMaxFrameRetries The maximum number of retries allowed after a transmission failure. 1143 */ SetMaxFrameRetries(uint8_t aMaxFrameRetries)1144 void SetMaxFrameRetries(uint8_t aMaxFrameRetries) { mInfo.mTxInfo.mMaxFrameRetries = aMaxFrameRetries; } 1145 1146 /** 1147 * Indicates whether or not the frame is a retransmission. 1148 * 1149 * @retval TRUE Frame is a retransmission 1150 * @retval FALSE This is a new frame and not a retransmission of an earlier frame. 1151 */ IsARetransmission(void) const1152 bool IsARetransmission(void) const { return mInfo.mTxInfo.mIsARetx; } 1153 1154 /** 1155 * Sets the retransmission flag attribute. 1156 * 1157 * @param[in] aIsARetx TRUE if frame is a retransmission of an earlier frame, FALSE otherwise. 1158 */ SetIsARetransmission(bool aIsARetx)1159 void SetIsARetransmission(bool aIsARetx) { mInfo.mTxInfo.mIsARetx = aIsARetx; } 1160 1161 /** 1162 * Indicates whether or not CSMA-CA is enabled. 1163 * 1164 * @retval TRUE CSMA-CA is enabled. 1165 * @retval FALSE CSMA-CA is not enabled is not enabled. 1166 */ IsCsmaCaEnabled(void) const1167 bool IsCsmaCaEnabled(void) const { return mInfo.mTxInfo.mCsmaCaEnabled; } 1168 1169 /** 1170 * Sets the CSMA-CA enabled attribute. 1171 * 1172 * @param[in] aCsmaCaEnabled TRUE if CSMA-CA must be enabled for this packet, FALSE otherwise. 1173 */ SetCsmaCaEnabled(bool aCsmaCaEnabled)1174 void SetCsmaCaEnabled(bool aCsmaCaEnabled) { mInfo.mTxInfo.mCsmaCaEnabled = aCsmaCaEnabled; } 1175 1176 /** 1177 * Returns the key used for frame encryption and authentication (AES CCM). 1178 * 1179 * @returns The pointer to the key. 1180 */ GetAesKey(void) const1181 const Mac::KeyMaterial &GetAesKey(void) const 1182 { 1183 return *static_cast<const Mac::KeyMaterial *>(mInfo.mTxInfo.mAesKey); 1184 } 1185 1186 /** 1187 * Sets the key used for frame encryption and authentication (AES CCM). 1188 * 1189 * @param[in] aAesKey The pointer to the key. 1190 */ SetAesKey(const Mac::KeyMaterial & aAesKey)1191 void SetAesKey(const Mac::KeyMaterial &aAesKey) { mInfo.mTxInfo.mAesKey = &aAesKey; } 1192 1193 /** 1194 * Copies the PSDU and all attributes (except for frame link type) from another frame. 1195 * 1196 * @note This method performs a deep copy meaning the content of PSDU buffer from the given frame is copied into 1197 * the PSDU buffer of the current frame. 1198 1199 * @param[in] aFromFrame The frame to copy from. 1200 */ 1201 void CopyFrom(const TxFrame &aFromFrame); 1202 1203 /** 1204 * Performs AES CCM on the frame which is going to be sent. 1205 * 1206 * @param[in] aExtAddress A reference to the extended address, which will be used to generate nonce 1207 * for AES CCM computation. 1208 */ 1209 void ProcessTransmitAesCcm(const ExtAddress &aExtAddress); 1210 1211 /** 1212 * Indicates whether or not the frame has security processed. 1213 * 1214 * @retval TRUE The frame already has security processed. 1215 * @retval FALSE The frame does not have security processed. 1216 */ IsSecurityProcessed(void) const1217 bool IsSecurityProcessed(void) const { return mInfo.mTxInfo.mIsSecurityProcessed; } 1218 1219 /** 1220 * Sets the security processed flag attribute. 1221 * 1222 * @param[in] aIsSecurityProcessed TRUE if the frame already has security processed. 1223 */ SetIsSecurityProcessed(bool aIsSecurityProcessed)1224 void SetIsSecurityProcessed(bool aIsSecurityProcessed) 1225 { 1226 mInfo.mTxInfo.mIsSecurityProcessed = aIsSecurityProcessed; 1227 } 1228 1229 /** 1230 * Indicates whether or not the frame contains the CSL IE. 1231 * 1232 * @retval TRUE The frame contains the CSL IE. 1233 * @retval FALSE The frame does not contain the CSL IE. 1234 */ IsCslIePresent(void) const1235 bool IsCslIePresent(void) const { return mInfo.mTxInfo.mCslPresent; } 1236 1237 /** 1238 * Sets the CSL IE present flag. 1239 * 1240 * @param[in] aCslPresent TRUE if the frame contains the CSL IE. 1241 */ SetCslIePresent(bool aCslPresent)1242 void SetCslIePresent(bool aCslPresent) { mInfo.mTxInfo.mCslPresent = aCslPresent; } 1243 1244 /** 1245 * Indicates whether or not the frame header is updated. 1246 * 1247 * @retval TRUE The frame already has the header updated. 1248 * @retval FALSE The frame does not have the header updated. 1249 */ IsHeaderUpdated(void) const1250 bool IsHeaderUpdated(void) const { return mInfo.mTxInfo.mIsHeaderUpdated; } 1251 1252 /** 1253 * Sets the header updated flag attribute. 1254 * 1255 * @param[in] aIsHeaderUpdated TRUE if the frame header is updated. 1256 */ SetIsHeaderUpdated(bool aIsHeaderUpdated)1257 void SetIsHeaderUpdated(bool aIsHeaderUpdated) { mInfo.mTxInfo.mIsHeaderUpdated = aIsHeaderUpdated; } 1258 1259 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1260 /** 1261 * Sets the Time IE offset. 1262 * 1263 * @param[in] aOffset The Time IE offset, 0 means no Time IE. 1264 */ SetTimeIeOffset(uint8_t aOffset)1265 void SetTimeIeOffset(uint8_t aOffset) { mInfo.mTxInfo.mIeInfo->mTimeIeOffset = aOffset; } 1266 1267 /** 1268 * Gets the Time IE offset. 1269 * 1270 * @returns The Time IE offset, 0 means no Time IE. 1271 */ GetTimeIeOffset(void) const1272 uint8_t GetTimeIeOffset(void) const { return mInfo.mTxInfo.mIeInfo->mTimeIeOffset; } 1273 1274 /** 1275 * Sets the offset to network time. 1276 * 1277 * @param[in] aNetworkTimeOffset The offset to network time. 1278 */ SetNetworkTimeOffset(int64_t aNetworkTimeOffset)1279 void SetNetworkTimeOffset(int64_t aNetworkTimeOffset) 1280 { 1281 mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset = aNetworkTimeOffset; 1282 } 1283 1284 /** 1285 * Sets the time sync sequence. 1286 * 1287 * @param[in] aTimeSyncSeq The time sync sequence. 1288 */ SetTimeSyncSeq(uint8_t aTimeSyncSeq)1289 void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { mInfo.mTxInfo.mIeInfo->mTimeSyncSeq = aTimeSyncSeq; } 1290 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1291 1292 /** 1293 * Generate Imm-Ack in this frame object. 1294 * 1295 * @param[in] aFrame A reference to the frame received. 1296 * @param[in] aIsFramePending Value of the ACK's frame pending bit. 1297 */ 1298 void GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending); 1299 1300 /** 1301 * Generate Enh-Ack in this frame object. 1302 * 1303 * @param[in] aRxFrame A reference to the received frame. 1304 * @param[in] aIsFramePending Value of the ACK's frame pending bit. 1305 * @param[in] aIeData A pointer to the IE data portion of the ACK to be sent. 1306 * @param[in] aIeLength The length of IE data portion of the ACK to be sent. 1307 * 1308 * @retval kErrorNone Successfully generated Enh Ack. 1309 * @retval kErrorParse @p aRxFrame has incorrect format. 1310 */ 1311 Error GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength); 1312 1313 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE 1314 /** 1315 * Generate IEE 802.15.4 Wake-up frame. 1316 * 1317 * @param[in] aPanId A destination PAN identifier 1318 * @param[in] aDest A destination address (short or extended) 1319 * @param[in] aSource A source address (short or extended) 1320 * 1321 * @retval kErrorNone Successfully generated Wake-up frame. 1322 * @retval kErrorInvalidArgs @p aDest or @p aSource have incorrect type. 1323 */ 1324 Error GenerateWakeupFrame(PanId aPanId, const Address &aDest, const Address &aSource); 1325 #endif 1326 1327 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 1328 /** 1329 * Set TX delay field for the frame. 1330 * 1331 * @param[in] aTxDelay The delay time for the TX frame. 1332 */ SetTxDelay(uint32_t aTxDelay)1333 void SetTxDelay(uint32_t aTxDelay) { mInfo.mTxInfo.mTxDelay = aTxDelay; } 1334 1335 /** 1336 * Set TX delay base time field for the frame. 1337 * 1338 * @param[in] aTxDelayBaseTime The delay base time for the TX frame. 1339 */ SetTxDelayBaseTime(uint32_t aTxDelayBaseTime)1340 void SetTxDelayBaseTime(uint32_t aTxDelayBaseTime) { mInfo.mTxInfo.mTxDelayBaseTime = aTxDelayBaseTime; } 1341 #endif 1342 }; 1343 1344 OT_TOOL_PACKED_BEGIN 1345 class Beacon 1346 { 1347 public: 1348 static constexpr uint16_t kSuperFrameSpec = 0x0fff; ///< Superframe Specification value. 1349 1350 /** 1351 * Initializes the Beacon message. 1352 */ Init(void)1353 void Init(void) 1354 { 1355 mSuperframeSpec = LittleEndian::HostSwap16(kSuperFrameSpec); 1356 mGtsSpec = 0; 1357 mPendingAddressSpec = 0; 1358 } 1359 1360 /** 1361 * Indicates whether or not the beacon appears to be a valid Thread Beacon message. 1362 * 1363 * @retval TRUE If the beacon appears to be a valid Thread Beacon message. 1364 * @retval FALSE If the beacon does not appear to be a valid Thread Beacon message. 1365 */ IsValid(void) const1366 bool IsValid(void) const 1367 { 1368 return (mSuperframeSpec == LittleEndian::HostSwap16(kSuperFrameSpec)) && (mGtsSpec == 0) && 1369 (mPendingAddressSpec == 0); 1370 } 1371 1372 /** 1373 * Returns the pointer to the beacon payload. 1374 * 1375 * @returns A pointer to the beacon payload. 1376 */ GetPayload(void)1377 uint8_t *GetPayload(void) { return reinterpret_cast<uint8_t *>(this) + sizeof(*this); } 1378 1379 /** 1380 * Returns the pointer to the beacon payload. 1381 * 1382 * @returns A pointer to the beacon payload. 1383 */ GetPayload(void) const1384 const uint8_t *GetPayload(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); } 1385 1386 private: 1387 uint16_t mSuperframeSpec; 1388 uint8_t mGtsSpec; 1389 uint8_t mPendingAddressSpec; 1390 } OT_TOOL_PACKED_END; 1391 1392 /** 1393 * Implements IEEE 802.15.4 Beacon Payload generation and parsing. 1394 */ 1395 OT_TOOL_PACKED_BEGIN 1396 class BeaconPayload 1397 { 1398 public: 1399 static constexpr uint8_t kProtocolId = 3; ///< Thread Protocol ID. 1400 static constexpr uint8_t kProtocolVersion = 2; ///< Thread Protocol version. 1401 static constexpr uint8_t kVersionOffset = 4; ///< Version field bit offset. 1402 static constexpr uint8_t kVersionMask = 0xf << kVersionOffset; ///< Version field mask. 1403 static constexpr uint8_t kNativeFlag = 1 << 3; ///< Native Commissioner flag. 1404 static constexpr uint8_t kJoiningFlag = 1 << 0; ///< Joining Permitted flag. 1405 1406 /** 1407 * Initializes the Beacon Payload. 1408 */ Init(void)1409 void Init(void) 1410 { 1411 mProtocolId = kProtocolId; 1412 mFlags = kProtocolVersion << kVersionOffset; 1413 } 1414 1415 /** 1416 * Indicates whether or not the beacon appears to be a valid Thread Beacon Payload. 1417 * 1418 * @retval TRUE If the beacon appears to be a valid Thread Beacon Payload. 1419 * @retval FALSE If the beacon does not appear to be a valid Thread Beacon Payload. 1420 */ IsValid(void) const1421 bool IsValid(void) const { return (mProtocolId == kProtocolId); } 1422 1423 /** 1424 * Returns the Protocol ID value. 1425 * 1426 * @returns the Protocol ID value. 1427 */ GetProtocolId(void) const1428 uint8_t GetProtocolId(void) const { return mProtocolId; } 1429 1430 /** 1431 * Returns the Protocol Version value. 1432 * 1433 * @returns The Protocol Version value. 1434 */ GetProtocolVersion(void) const1435 uint8_t GetProtocolVersion(void) const { return mFlags >> kVersionOffset; } 1436 1437 /** 1438 * Indicates whether or not the Native Commissioner flag is set. 1439 * 1440 * @retval TRUE If the Native Commissioner flag is set. 1441 * @retval FALSE If the Native Commissioner flag is not set. 1442 */ IsNative(void) const1443 bool IsNative(void) const { return (mFlags & kNativeFlag) != 0; } 1444 1445 /** 1446 * Clears the Native Commissioner flag. 1447 */ ClearNative(void)1448 void ClearNative(void) { mFlags &= ~kNativeFlag; } 1449 1450 /** 1451 * Sets the Native Commissioner flag. 1452 */ SetNative(void)1453 void SetNative(void) { mFlags |= kNativeFlag; } 1454 1455 /** 1456 * Indicates whether or not the Joining Permitted flag is set. 1457 * 1458 * @retval TRUE If the Joining Permitted flag is set. 1459 * @retval FALSE If the Joining Permitted flag is not set. 1460 */ IsJoiningPermitted(void) const1461 bool IsJoiningPermitted(void) const { return (mFlags & kJoiningFlag) != 0; } 1462 1463 /** 1464 * Clears the Joining Permitted flag. 1465 */ ClearJoiningPermitted(void)1466 void ClearJoiningPermitted(void) { mFlags &= ~kJoiningFlag; } 1467 1468 /** 1469 * Sets the Joining Permitted flag. 1470 */ SetJoiningPermitted(void)1471 void SetJoiningPermitted(void) 1472 { 1473 mFlags |= kJoiningFlag; 1474 1475 #if OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION != 2 // check against kProtocolVersion 1476 mFlags &= ~kVersionMask; 1477 mFlags |= OPENTHREAD_CONFIG_MAC_JOIN_BEACON_VERSION << kVersionOffset; 1478 #endif 1479 } 1480 1481 /** 1482 * Gets the Network Name field. 1483 * 1484 * @returns The Network Name field as `NameData`. 1485 */ GetNetworkName(void) const1486 MeshCoP::NameData GetNetworkName(void) const { return MeshCoP::NameData(mNetworkName, sizeof(mNetworkName)); } 1487 1488 /** 1489 * Sets the Network Name field. 1490 * 1491 * @param[in] aNameData The Network Name (as a `NameData`). 1492 */ SetNetworkName(const MeshCoP::NameData & aNameData)1493 void SetNetworkName(const MeshCoP::NameData &aNameData) { aNameData.CopyTo(mNetworkName, sizeof(mNetworkName)); } 1494 1495 /** 1496 * Returns the Extended PAN ID field. 1497 * 1498 * @returns The Extended PAN ID field. 1499 */ GetExtendedPanId(void) const1500 const otExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; } 1501 1502 /** 1503 * Sets the Extended PAN ID field. 1504 * 1505 * @param[in] aExtPanId An Extended PAN ID. 1506 */ SetExtendedPanId(const otExtendedPanId & aExtPanId)1507 void SetExtendedPanId(const otExtendedPanId &aExtPanId) { mExtendedPanId = aExtPanId; } 1508 1509 private: 1510 uint8_t mProtocolId; 1511 uint8_t mFlags; 1512 char mNetworkName[MeshCoP::NetworkName::kMaxSize]; 1513 otExtendedPanId mExtendedPanId; 1514 } OT_TOOL_PACKED_END; 1515 1516 /** 1517 * @} 1518 */ 1519 1520 } // namespace Mac 1521 } // namespace ot 1522 1523 #endif // MAC_FRAME_HPP_ 1524