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