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 the IEEE 802.15.4 MAC. 32 */ 33 34 #ifndef MAC_HPP_ 35 #define MAC_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <openthread/platform/radio.h> 40 #include <openthread/platform/time.h> 41 42 #include "common/clearable.hpp" 43 #include "common/locator.hpp" 44 #include "common/log.hpp" 45 #include "common/non_copyable.hpp" 46 #include "common/tasklet.hpp" 47 #include "common/time.hpp" 48 #include "common/timer.hpp" 49 #include "mac/channel_mask.hpp" 50 #include "mac/mac_filter.hpp" 51 #include "mac/mac_frame.hpp" 52 #include "mac/mac_links.hpp" 53 #include "mac/mac_types.hpp" 54 #include "mac/sub_mac.hpp" 55 #include "radio/trel_link.hpp" 56 #include "thread/key_manager.hpp" 57 #include "thread/link_quality.hpp" 58 59 namespace ot { 60 61 class Neighbor; 62 63 /** 64 * @addtogroup core-mac 65 * 66 * @brief 67 * This module includes definitions for the IEEE 802.15.4 MAC 68 * 69 * @{ 70 * 71 */ 72 73 namespace Mac { 74 75 constexpr uint32_t kDataPollTimeout = 76 OPENTHREAD_CONFIG_MAC_DATA_POLL_TIMEOUT; ///< Timeout for receiving Data Frame (in msec). 77 constexpr uint32_t kSleepDelay = 300; ///< Max sleep delay when frame is pending (in msec). 78 79 constexpr uint16_t kScanDurationDefault = OPENTHREAD_CONFIG_MAC_SCAN_DURATION; ///< Duration per channel (in msec). 80 81 constexpr uint8_t kMaxCsmaBackoffsDirect = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT; 82 constexpr uint8_t kMaxCsmaBackoffsIndirect = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_INDIRECT; 83 constexpr uint8_t kMaxCsmaBackoffsCsl = 0; 84 85 constexpr uint8_t kDefaultMaxFrameRetriesDirect = OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT; 86 constexpr uint8_t kDefaultMaxFrameRetriesIndirect = OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_INDIRECT; 87 constexpr uint8_t kMaxFrameRetriesCsl = 0; 88 89 constexpr uint8_t kTxNumBcast = OPENTHREAD_CONFIG_MAC_TX_NUM_BCAST; ///< Num of times broadcast frame is tx. 90 91 constexpr uint16_t kMinCslIePeriod = OPENTHREAD_CONFIG_MAC_CSL_MIN_PERIOD; 92 93 /** 94 * Defines the function pointer called on receiving an IEEE 802.15.4 Beacon during an Active Scan. 95 * 96 */ 97 typedef otHandleActiveScanResult ActiveScanHandler; 98 99 /** 100 * Defines an Active Scan result. 101 * 102 */ 103 typedef otActiveScanResult ActiveScanResult; 104 105 /** 106 * Defines the function pointer which is called during an Energy Scan when the scan result for a channel is 107 * ready or when the scan completes. 108 * 109 */ 110 typedef otHandleEnergyScanResult EnergyScanHandler; 111 112 /** 113 * Defines an Energy Scan result. 114 * 115 */ 116 typedef otEnergyScanResult EnergyScanResult; 117 118 /** 119 * Implements the IEEE 802.15.4 MAC. 120 * 121 */ 122 class Mac : public InstanceLocator, private NonCopyable 123 { 124 friend class ot::Instance; 125 126 public: 127 /** 128 * Initializes the MAC object. 129 * 130 * @param[in] aInstance A reference to the OpenThread instance. 131 * 132 */ 133 explicit Mac(Instance &aInstance); 134 135 /** 136 * Starts an IEEE 802.15.4 Active Scan. 137 * 138 * @param[in] aScanChannels A bit vector indicating which channels to scan. Zero is mapped to all channels. 139 * @param[in] aScanDuration The time in milliseconds to spend scanning each channel. Zero duration maps to 140 * default value `kScanDurationDefault` = 300 ms. 141 * @param[in] aHandler A pointer to a function that is called on receiving an IEEE 802.15.4 Beacon. 142 * @param[in] aContext A pointer to an arbitrary context (used when invoking `aHandler` callback). 143 * 144 * @retval kErrorNone Successfully scheduled the Active Scan request. 145 * @retval kErrorBusy Could not schedule the scan (a scan is ongoing or scheduled). 146 * 147 */ 148 Error ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext); 149 150 /** 151 * Starts an IEEE 802.15.4 Energy Scan. 152 * 153 * @param[in] aScanChannels A bit vector indicating on which channels to scan. Zero is mapped to all channels. 154 * @param[in] aScanDuration The time in milliseconds to spend scanning each channel. If the duration is set to 155 * zero, a single RSSI sample will be taken per channel. 156 * @param[in] aHandler A pointer to a function called to pass on scan result or indicate scan completion. 157 * @param[in] aContext A pointer to an arbitrary context (used when invoking @p aHandler callback). 158 * 159 * @retval kErrorNone Accepted the Energy Scan request. 160 * @retval kErrorBusy Could not start the energy scan. 161 * 162 */ 163 Error EnergyScan(uint32_t aScanChannels, uint16_t aScanDuration, EnergyScanHandler aHandler, void *aContext); 164 165 /** 166 * Indicates the energy scan for the current channel is complete. 167 * 168 * @param[in] aEnergyScanMaxRssi The maximum RSSI encountered on the scanned channel. 169 * 170 */ 171 void EnergyScanDone(int8_t aEnergyScanMaxRssi); 172 173 /** 174 * Indicates whether or not IEEE 802.15.4 Beacon transmissions are enabled. 175 * 176 * @retval TRUE If IEEE 802.15.4 Beacon transmissions are enabled. 177 * @retval FALSE If IEEE 802.15.4 Beacon transmissions are not enabled. 178 * 179 */ IsBeaconEnabled(void) const180 bool IsBeaconEnabled(void) const { return mBeaconsEnabled; } 181 182 /** 183 * Enables/disables IEEE 802.15.4 Beacon transmissions. 184 * 185 * @param[in] aEnabled TRUE to enable IEEE 802.15.4 Beacon transmissions, FALSE otherwise. 186 * 187 */ SetBeaconEnabled(bool aEnabled)188 void SetBeaconEnabled(bool aEnabled) { mBeaconsEnabled = aEnabled; } 189 190 /** 191 * Indicates whether or not rx-on-when-idle is enabled. 192 * 193 * @retval TRUE If rx-on-when-idle is enabled. 194 * @retval FALSE If rx-on-when-idle is not enabled. 195 */ GetRxOnWhenIdle(void) const196 bool GetRxOnWhenIdle(void) const { return mRxOnWhenIdle; } 197 198 /** 199 * Sets the rx-on-when-idle mode. 200 * 201 * @param[in] aRxOnWhenIdle The rx-on-when-idle mode. 202 * 203 */ 204 void SetRxOnWhenIdle(bool aRxOnWhenIdle); 205 206 /** 207 * Requests a direct data frame transmission. 208 * 209 */ 210 void RequestDirectFrameTransmission(void); 211 212 #if OPENTHREAD_FTD 213 /** 214 * Requests an indirect data frame transmission. 215 * 216 */ 217 void RequestIndirectFrameTransmission(void); 218 219 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 220 /** 221 * Requests `Mac` to start a CSL tx operation after a delay of @p aDelay time. 222 * 223 * @param[in] aDelay Delay time for `Mac` to start a CSL tx, in units of milliseconds. 224 * 225 */ 226 void RequestCslFrameTransmission(uint32_t aDelay); 227 #endif 228 229 #endif 230 231 /** 232 * Requests transmission of a data poll (MAC Data Request) frame. 233 * 234 * @retval kErrorNone Data poll transmission request is scheduled successfully. 235 * @retval kErrorInvalidState The MAC layer is not enabled. 236 * 237 */ 238 Error RequestDataPollTransmission(void); 239 240 /** 241 * Returns a reference to the IEEE 802.15.4 Extended Address. 242 * 243 * @returns A pointer to the IEEE 802.15.4 Extended Address. 244 * 245 */ GetExtAddress(void) const246 const ExtAddress &GetExtAddress(void) const { return mLinks.GetExtAddress(); } 247 248 /** 249 * Sets the IEEE 802.15.4 Extended Address. 250 * 251 * @param[in] aExtAddress A reference to the IEEE 802.15.4 Extended Address. 252 * 253 */ SetExtAddress(const ExtAddress & aExtAddress)254 void SetExtAddress(const ExtAddress &aExtAddress) { mLinks.SetExtAddress(aExtAddress); } 255 256 /** 257 * Returns the IEEE 802.15.4 Short Address. 258 * 259 * @returns The IEEE 802.15.4 Short Address. 260 * 261 */ GetShortAddress(void) const262 ShortAddress GetShortAddress(void) const { return mLinks.GetShortAddress(); } 263 264 /** 265 * Sets the IEEE 802.15.4 Short Address. 266 * 267 * @param[in] aShortAddress The IEEE 802.15.4 Short Address. 268 * 269 */ SetShortAddress(ShortAddress aShortAddress)270 void SetShortAddress(ShortAddress aShortAddress) { mLinks.SetShortAddress(aShortAddress); } 271 272 /** 273 * Returns the IEEE 802.15.4 PAN Channel. 274 * 275 * @returns The IEEE 802.15.4 PAN Channel. 276 * 277 */ GetPanChannel(void) const278 uint8_t GetPanChannel(void) const { return mPanChannel; } 279 280 /** 281 * Sets the IEEE 802.15.4 PAN Channel. 282 * 283 * @param[in] aChannel The IEEE 802.15.4 PAN Channel. 284 * 285 * @retval kErrorNone Successfully set the IEEE 802.15.4 PAN Channel. 286 * @retval kErrorInvalidArgs The @p aChannel is not in the supported channel mask. 287 * 288 */ 289 Error SetPanChannel(uint8_t aChannel); 290 291 /** 292 * Sets the temporary IEEE 802.15.4 radio channel. 293 * 294 * Allows user to temporarily change the radio channel and use a different channel (during receive) 295 * instead of the PAN channel (from `SetPanChannel()`). A call to `ClearTemporaryChannel()` would clear the 296 * temporary channel and adopt the PAN channel again. The `SetTemporaryChannel()` can be used multiple times in row 297 * (before a call to `ClearTemporaryChannel()`) to change the temporary channel. 298 * 299 * @param[in] aChannel A IEEE 802.15.4 channel. 300 * 301 * @retval kErrorNone Successfully set the temporary channel 302 * @retval kErrorInvalidArgs The @p aChannel is not in the supported channel mask. 303 * 304 */ 305 Error SetTemporaryChannel(uint8_t aChannel); 306 307 /** 308 * Clears the use of a previously set temporary channel and adopts the PAN channel. 309 * 310 */ 311 void ClearTemporaryChannel(void); 312 313 /** 314 * Returns the supported channel mask. 315 * 316 * @returns The supported channel mask. 317 * 318 */ GetSupportedChannelMask(void) const319 const ChannelMask &GetSupportedChannelMask(void) const { return mSupportedChannelMask; } 320 321 /** 322 * Sets the supported channel mask 323 * 324 * @param[in] aMask The supported channel mask. 325 * 326 */ 327 void SetSupportedChannelMask(const ChannelMask &aMask); 328 329 /** 330 * Returns the IEEE 802.15.4 PAN ID. 331 * 332 * @returns The IEEE 802.15.4 PAN ID. 333 * 334 */ GetPanId(void) const335 PanId GetPanId(void) const { return mPanId; } 336 337 /** 338 * Sets the IEEE 802.15.4 PAN ID. 339 * 340 * @param[in] aPanId The IEEE 802.15.4 PAN ID. 341 * 342 */ 343 void SetPanId(PanId aPanId); 344 345 /** 346 * Returns the maximum number of frame retries during direct transmission. 347 * 348 * @returns The maximum number of retries during direct transmission. 349 * 350 */ GetMaxFrameRetriesDirect(void) const351 uint8_t GetMaxFrameRetriesDirect(void) const { return mMaxFrameRetriesDirect; } 352 353 /** 354 * Sets the maximum number of frame retries during direct transmission. 355 * 356 * @param[in] aMaxFrameRetriesDirect The maximum number of retries during direct transmission. 357 * 358 */ SetMaxFrameRetriesDirect(uint8_t aMaxFrameRetriesDirect)359 void SetMaxFrameRetriesDirect(uint8_t aMaxFrameRetriesDirect) { mMaxFrameRetriesDirect = aMaxFrameRetriesDirect; } 360 361 #if OPENTHREAD_FTD 362 /** 363 * Returns the maximum number of frame retries during indirect transmission. 364 * 365 * @returns The maximum number of retries during indirect transmission. 366 * 367 */ GetMaxFrameRetriesIndirect(void) const368 uint8_t GetMaxFrameRetriesIndirect(void) const { return mMaxFrameRetriesIndirect; } 369 370 /** 371 * Sets the maximum number of frame retries during indirect transmission. 372 * 373 * @param[in] aMaxFrameRetriesIndirect The maximum number of retries during indirect transmission. 374 * 375 */ SetMaxFrameRetriesIndirect(uint8_t aMaxFrameRetriesIndirect)376 void SetMaxFrameRetriesIndirect(uint8_t aMaxFrameRetriesIndirect) 377 { 378 mMaxFrameRetriesIndirect = aMaxFrameRetriesIndirect; 379 } 380 #endif 381 382 /** 383 * Is called to handle a received frame. 384 * 385 * @param[in] aFrame A pointer to the received frame, or `nullptr` if the receive operation was aborted. 386 * @param[in] aError kErrorNone when successfully received a frame, 387 * kErrorAbort when reception was aborted and a frame was not received. 388 * 389 */ 390 void HandleReceivedFrame(RxFrame *aFrame, Error aError); 391 392 /** 393 * Records CCA status (success/failure) for a frame transmission attempt. 394 * 395 * @param[in] aCcaSuccess TRUE if the CCA succeeded, FALSE otherwise. 396 * @param[in] aChannel The channel on which CCA was performed. 397 * 398 */ 399 void RecordCcaStatus(bool aCcaSuccess, uint8_t aChannel); 400 401 /** 402 * Records the status of a frame transmission attempt, updating MAC counters. 403 * 404 * Unlike `HandleTransmitDone` which is called after all transmission attempts of frame to indicate final status 405 * of a frame transmission request, this method is invoked on all frame transmission attempts. 406 * 407 * @param[in] aFrame The transmitted frame. 408 * @param[in] aError kErrorNone when the frame was transmitted successfully, 409 * kErrorNoAck when the frame was transmitted but no ACK was received, 410 * kErrorChannelAccessFailure tx failed due to activity on the channel, 411 * kErrorAbort when transmission was aborted for other reasons. 412 * @param[in] aRetryCount Indicates number of transmission retries for this frame. 413 * @param[in] aWillRetx Indicates whether frame will be retransmitted or not. This is applicable only 414 * when there was an error in transmission (i.e., `aError` is not NONE). 415 * 416 */ 417 void RecordFrameTransmitStatus(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx); 418 419 /** 420 * Is called to handle transmit events. 421 * 422 * @param[in] aFrame The frame that was transmitted. 423 * @param[in] aAckFrame A pointer to the ACK frame, `nullptr` if no ACK was received. 424 * @param[in] aError kErrorNone when the frame was transmitted successfully, 425 * kErrorNoAck when the frame was transmitted but no ACK was received, 426 * kErrorChannelAccessFailure when the tx failed due to activity on the channel, 427 * kErrorAbort when transmission was aborted for other reasons. 428 * 429 */ 430 void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError); 431 432 /** 433 * Returns if an active scan is in progress. 434 * 435 */ IsActiveScanInProgress(void) const436 bool IsActiveScanInProgress(void) const { return IsActiveOrPending(kOperationActiveScan); } 437 438 /** 439 * Returns if an energy scan is in progress. 440 * 441 */ IsEnergyScanInProgress(void) const442 bool IsEnergyScanInProgress(void) const { return IsActiveOrPending(kOperationEnergyScan); } 443 444 #if OPENTHREAD_FTD 445 /** 446 * Indicates whether the MAC layer is performing an indirect transmission (in middle of a tx). 447 * 448 * @returns TRUE if in middle of an indirect transmission, FALSE otherwise. 449 * 450 */ IsPerformingIndirectTransmit(void) const451 bool IsPerformingIndirectTransmit(void) const { return (mOperation == kOperationTransmitDataIndirect); } 452 #endif 453 454 /** 455 * Returns if the MAC layer is in transmit state. 456 * 457 * The MAC layer is in transmit state during CSMA/CA, CCA, transmission of Data, Beacon or Data Request frames and 458 * receiving of ACK frames. The MAC layer is not in transmit state during transmission of ACK frames or Beacon 459 * Requests. 460 * 461 */ 462 bool IsInTransmitState(void) const; 463 464 /** 465 * Registers a callback to provide received raw IEEE 802.15.4 frames. 466 * 467 * @param[in] aPcapCallback A pointer to a function that is called when receiving an IEEE 802.15.4 link frame 468 * or `nullptr` to disable the callback. 469 * @param[in] aCallbackContext A pointer to application-specific context. 470 * 471 */ SetPcapCallback(otLinkPcapCallback aPcapCallback,void * aCallbackContext)472 void SetPcapCallback(otLinkPcapCallback aPcapCallback, void *aCallbackContext) 473 { 474 mLinks.SetPcapCallback(aPcapCallback, aCallbackContext); 475 } 476 477 /** 478 * Indicates whether or not promiscuous mode is enabled at the link layer. 479 * 480 * @retval true Promiscuous mode is enabled. 481 * @retval false Promiscuous mode is not enabled. 482 * 483 */ IsPromiscuous(void) const484 bool IsPromiscuous(void) const { return mPromiscuous; } 485 486 /** 487 * Enables or disables the link layer promiscuous mode. 488 * 489 * Promiscuous mode keeps the receiver enabled, overriding the value of mRxOnWhenIdle. 490 * 491 * @param[in] aPromiscuous true to enable promiscuous mode, or false otherwise. 492 * 493 */ 494 void SetPromiscuous(bool aPromiscuous); 495 496 /** 497 * Resets mac counters 498 * 499 */ ResetCounters(void)500 void ResetCounters(void) { ClearAllBytes(mCounters); } 501 502 /** 503 * Returns the MAC counter. 504 * 505 * @returns A reference to the MAC counter. 506 * 507 */ GetCounters(void)508 otMacCounters &GetCounters(void) { return mCounters; } 509 510 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 511 /** 512 * Returns the MAC retry histogram for direct transmission. 513 * 514 * @param[out] aNumberOfEntries A reference to where the size of returned histogram array is placed. 515 * 516 * @returns A pointer to the histogram of retries (in a form of an array). 517 * The n-th element indicates that the packet has been sent with n-th retry. 518 * 519 */ 520 const uint32_t *GetDirectRetrySuccessHistogram(uint8_t &aNumberOfEntries); 521 522 #if OPENTHREAD_FTD 523 /** 524 * Returns the MAC retry histogram for indirect transmission. 525 * 526 * @param[out] aNumberOfEntries A reference to where the size of returned histogram array is placed. 527 * 528 * @returns A pointer to the histogram of retries (in a form of an array). 529 * The n-th element indicates that the packet has been sent with n-th retry. 530 * 531 */ 532 const uint32_t *GetIndirectRetrySuccessHistogram(uint8_t &aNumberOfEntries); 533 #endif 534 535 /** 536 * Resets MAC retry histogram. 537 * 538 */ 539 void ResetRetrySuccessHistogram(void); 540 #endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 541 542 /** 543 * Returns the noise floor value (currently use the radio receive sensitivity value). 544 * 545 * @returns The noise floor value in dBm. 546 * 547 */ GetNoiseFloor(void) const548 int8_t GetNoiseFloor(void) const { return mLinks.GetNoiseFloor(); } 549 550 /** 551 * Computes the link margin for a given a received signal strength value using noise floor. 552 * 553 * @param[in] aRss The received signal strength in dBm. 554 * 555 * @returns The link margin for @p aRss in dB based on noise floor. 556 * 557 */ 558 uint8_t ComputeLinkMargin(int8_t aRss) const; 559 560 /** 561 * Returns the current CCA (Clear Channel Assessment) failure rate. 562 * 563 * The rate is maintained over a window of (roughly) last `OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW` 564 * frame transmissions. 565 * 566 * @returns The CCA failure rate with maximum value `0xffff` corresponding to 100% failure rate. 567 * 568 */ GetCcaFailureRate(void) const569 uint16_t GetCcaFailureRate(void) const { return mCcaSuccessRateTracker.GetFailureRate(); } 570 571 /** 572 * Starts/Stops the Link layer. It may only be used when the Netif Interface is down. 573 * 574 * @param[in] aEnable The requested State for the MAC layer. true - Start, false - Stop. 575 * 576 */ 577 void SetEnabled(bool aEnable); 578 579 /** 580 * Indicates whether or not the link layer is enabled. 581 * 582 * @retval true Link layer is enabled. 583 * @retval false Link layer is not enabled. 584 * 585 */ IsEnabled(void) const586 bool IsEnabled(void) const { return mEnabled; } 587 588 /** 589 * Clears the Mode2Key stored in PSA ITS. 590 * 591 */ ClearMode2Key(void)592 void ClearMode2Key(void) { mMode2KeyMaterial.Clear(); } 593 594 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 595 /** 596 * Gets the CSL channel. 597 * 598 * @returns CSL channel. 599 * 600 */ GetCslChannel(void) const601 uint8_t GetCslChannel(void) const { return mCslChannel; } 602 603 /** 604 * Sets the CSL channel. 605 * 606 * @param[in] aChannel The CSL channel. 607 * 608 */ 609 void SetCslChannel(uint8_t aChannel); 610 611 /** 612 * Centralizes CSL state switching conditions evaluating, configuring SubMac accordingly. 613 * 614 */ 615 void UpdateCsl(void); 616 617 /** 618 * Gets the CSL period. 619 * 620 * @returns CSL period in units of 10 symbols. 621 * 622 */ GetCslPeriod(void) const623 uint16_t GetCslPeriod(void) const { return mCslPeriod; } 624 625 /** 626 * Gets the CSL period in milliseconds. 627 * 628 * If the CSL period cannot be represented exactly in milliseconds, return the rounded value to the nearest 629 * millisecond. 630 * 631 * @returns CSL period in milliseconds. 632 * 633 */ 634 uint32_t GetCslPeriodInMsec(void) const; 635 636 /** 637 * Sets the CSL period. 638 * 639 * @param[in] aPeriod The CSL period in 10 symbols. 640 * 641 */ 642 void SetCslPeriod(uint16_t aPeriod); 643 644 /** 645 * This method converts a given CSL period in units of 10 symbols to microseconds. 646 * 647 * @param[in] aPeriodInTenSymbols The CSL period in unit of 10 symbols. 648 * 649 * @returns The converted CSL period value in microseconds corresponding to @p aPeriodInTenSymbols. 650 * 651 */ 652 static uint32_t CslPeriodToUsec(uint16_t aPeriodInTenSymbols); 653 654 /** 655 * Indicates whether CSL is started at the moment. 656 * 657 * @retval TRUE If CSL is enabled. 658 * @retval FALSE If CSL is not enabled. 659 * 660 */ 661 bool IsCslEnabled(void) const; 662 663 /** 664 * Indicates whether Link is capable of starting CSL. 665 * 666 * @retval TRUE If Link is capable of starting CSL. 667 * @retval FALSE If link is not capable of starting CSL. 668 * 669 */ 670 bool IsCslCapable(void) const; 671 672 /** 673 * Indicates whether the device is connected to a parent which supports CSL. 674 * 675 * @retval TRUE If parent supports CSL. 676 * @retval FALSE If parent does not support CSL. 677 * 678 */ 679 bool IsCslSupported(void) const; 680 681 /** 682 * Returns parent CSL accuracy (clock accuracy and uncertainty). 683 * 684 * @returns The parent CSL accuracy. 685 * 686 */ GetCslParentAccuracy(void) const687 const CslAccuracy &GetCslParentAccuracy(void) const { return mLinks.GetSubMac().GetCslParentAccuracy(); } 688 689 /** 690 * Sets parent CSL accuracy. 691 * 692 * @param[in] aCslAccuracy The parent CSL accuracy. 693 * 694 */ SetCslParentAccuracy(const CslAccuracy & aCslAccuracy)695 void SetCslParentAccuracy(const CslAccuracy &aCslAccuracy) 696 { 697 mLinks.GetSubMac().SetCslParentAccuracy(aCslAccuracy); 698 } 699 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 700 701 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE 702 /** 703 * Enables/disables the 802.15.4 radio filter. 704 * 705 * When radio filter is enabled, radio is put to sleep instead of receive (to ensure device does not receive any 706 * frame and/or potentially send ack). Also the frame transmission requests return immediately without sending the 707 * frame over the air (return "no ack" error if ack is requested, otherwise return success). 708 * 709 * @param[in] aFilterEnabled TRUE to enable radio filter, FALSE to disable. 710 * 711 */ 712 void SetRadioFilterEnabled(bool aFilterEnabled); 713 714 /** 715 * Indicates whether the 802.15.4 radio filter is enabled or not. 716 * 717 * @retval TRUE If the radio filter is enabled. 718 * @retval FALSE If the radio filter is disabled. 719 * 720 */ IsRadioFilterEnabled(void) const721 bool IsRadioFilterEnabled(void) const { return mLinks.GetSubMac().IsRadioFilterEnabled(); } 722 #endif 723 724 /** 725 * Sets the region code. 726 * 727 * The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code. 728 * 729 * @param[in] aRegionCode The radio region code. The `aRegionCode >> 8` is first ascii char 730 * and the `aRegionCode & 0xff` is the second ascii char. 731 * 732 * @retval kErrorFailed Other platform specific errors. 733 * @retval kErrorNone Successfully set region code. 734 * @retval kErrorNotImplemented The feature is not implemented. 735 * 736 */ 737 Error SetRegion(uint16_t aRegionCode); 738 739 /** 740 * Get the region code. 741 * 742 * The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code. 743 * 744 * @param[out] aRegionCode The radio region code. The `aRegionCode >> 8` is first ascii char 745 * and the `aRegionCode & 0xff` is the second ascii char. 746 * 747 * @retval kErrorFailed Other platform specific errors. 748 * @retval kErrorNone Successfully set region code. 749 * @retval kErrorNotImplemented The feature is not implemented. 750 * 751 */ 752 Error GetRegion(uint16_t &aRegionCode) const; 753 754 private: 755 static constexpr uint16_t kMaxCcaSampleCount = OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW; 756 757 enum Operation : uint8_t 758 { 759 kOperationIdle = 0, 760 kOperationActiveScan, 761 kOperationEnergyScan, 762 kOperationTransmitBeacon, 763 kOperationTransmitDataDirect, 764 kOperationTransmitPoll, 765 kOperationWaitingForData, 766 #if OPENTHREAD_FTD 767 kOperationTransmitDataIndirect, 768 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 769 kOperationTransmitDataCsl, 770 #endif 771 #endif 772 }; 773 774 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 775 struct RetryHistogram 776 { 777 /** 778 * Histogram of number of retries for a single direct packet until success 779 * [0 retry: packet count, 1 retry: packet count, 2 retry : packet count ... 780 * until max retry limit: packet count] 781 * 782 * The size of the array is OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_DIRECT. 783 */ 784 uint32_t mTxDirectRetrySuccess[OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_DIRECT]; 785 786 /** 787 * Histogram of number of retries for a single indirect packet until success 788 * [0 retry: packet count, 1 retry: packet count, 2 retry : packet count ... 789 * until max retry limit: packet count] 790 * 791 * The size of the array is OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_INDIRECT. 792 */ 793 uint32_t mTxIndirectRetrySuccess[OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_INDIRECT]; 794 }; 795 #endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 796 797 Error ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor); 798 void ProcessTransmitSecurity(TxFrame &aFrame); 799 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 800 Error ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame); 801 #endif 802 803 void UpdateIdleMode(void); IsPending(Operation aOperation) const804 bool IsPending(Operation aOperation) const { return mPendingOperations & (1U << aOperation); } 805 bool IsActiveOrPending(Operation aOperation) const; SetPending(Operation aOperation)806 void SetPending(Operation aOperation) { mPendingOperations |= (1U << aOperation); } ClearPending(Operation aOperation)807 void ClearPending(Operation aOperation) { mPendingOperations &= ~(1U << aOperation); } 808 void StartOperation(Operation aOperation); 809 void FinishOperation(void); 810 void PerformNextOperation(void); 811 TxFrame *PrepareBeaconRequest(void); 812 TxFrame *PrepareBeacon(void); 813 bool ShouldSendBeacon(void) const; 814 bool IsJoinable(void) const; 815 void BeginTransmit(void); 816 void UpdateNeighborLinkInfo(Neighbor &aNeighbor, const RxFrame &aRxFrame); 817 bool HandleMacCommand(RxFrame &aFrame); 818 void HandleTimer(void); 819 820 void Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanDuration); 821 Error UpdateScanChannel(void); 822 void PerformActiveScan(void); 823 void ReportActiveScanResult(const RxFrame *aBeaconFrame); 824 Error ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult); 825 void PerformEnergyScan(void); 826 void ReportEnergyScanResult(int8_t aRssi); 827 828 void LogFrameRxFailure(const RxFrame *aFrame, Error aError) const; 829 void LogFrameTxFailure(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx) const; 830 void LogBeacon(const char *aActionText) const; 831 832 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 833 uint8_t GetTimeIeOffset(const Frame &aFrame); 834 #endif 835 836 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 837 void ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr); 838 #endif 839 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 840 void ProcessEnhAckProbing(const RxFrame &aFrame, const Neighbor &aNeighbor); 841 #endif 842 static const char *OperationToString(Operation aOperation); 843 844 using OperationTask = TaskletIn<Mac, &Mac::PerformNextOperation>; 845 using MacTimer = TimerMilliIn<Mac, &Mac::HandleTimer>; 846 847 static const otExtAddress sMode2ExtAddress; 848 849 bool mEnabled : 1; 850 bool mShouldTxPollBeforeData : 1; 851 bool mRxOnWhenIdle : 1; 852 bool mPromiscuous : 1; 853 bool mBeaconsEnabled : 1; 854 bool mUsingTemporaryChannel : 1; 855 #if OPENTHREAD_CONFIG_MAC_STAY_AWAKE_BETWEEN_FRAGMENTS 856 bool mShouldDelaySleep : 1; 857 bool mDelayingSleep : 1; 858 #endif 859 Operation mOperation; 860 uint16_t mPendingOperations; 861 uint8_t mBeaconSequence; 862 uint8_t mDataSequence; 863 uint8_t mBroadcastTransmitCount; 864 PanId mPanId; 865 uint8_t mPanChannel; 866 uint8_t mRadioChannel; 867 ChannelMask mSupportedChannelMask; 868 uint8_t mScanChannel; 869 uint16_t mScanDuration; 870 ChannelMask mScanChannelMask; 871 uint8_t mMaxFrameRetriesDirect; 872 #if OPENTHREAD_FTD 873 uint8_t mMaxFrameRetriesIndirect; 874 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 875 TimeMilli mCslTxFireTime; 876 #endif 877 #endif 878 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 879 // When Mac::mCslChannel is 0, it indicates that CSL channel has not been specified by the upper layer. 880 uint8_t mCslChannel; 881 uint16_t mCslPeriod; 882 #endif 883 884 union 885 { 886 ActiveScanHandler mActiveScanHandler; 887 EnergyScanHandler mEnergyScanHandler; 888 }; 889 890 void *mScanHandlerContext; 891 892 Links mLinks; 893 OperationTask mOperationTask; 894 MacTimer mTimer; 895 otMacCounters mCounters; 896 uint32_t mKeyIdMode2FrameCounter; 897 SuccessRateTracker mCcaSuccessRateTracker; 898 uint16_t mCcaSampleCount; 899 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 900 RetryHistogram mRetryHistogram; 901 #endif 902 903 #if OPENTHREAD_CONFIG_MULTI_RADIO 904 RadioTypes mTxPendingRadioLinks; 905 RadioTypes mTxBeaconRadioLinks; 906 Error mTxError; 907 #endif 908 909 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE 910 Filter mFilter; 911 #endif 912 913 KeyMaterial mMode2KeyMaterial; 914 }; 915 916 /** 917 * @} 918 * 919 */ 920 921 } // namespace Mac 922 } // namespace ot 923 924 #endif // MAC_HPP_ 925