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