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 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 /** 91 * Specifies the number of microseconds ahead of time that the MAC layer should deliver a CSL frame to the sub-MAC 92 * layer. 93 */ 94 constexpr uint16_t kCslRequestAhead = OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US; 95 96 constexpr uint16_t kMinCslIePeriod = OPENTHREAD_CONFIG_MAC_CSL_MIN_PERIOD; 97 98 constexpr uint32_t kDefaultWedListenInterval = OPENTHREAD_CONFIG_WED_LISTEN_INTERVAL; 99 constexpr uint32_t kDefaultWedListenDuration = OPENTHREAD_CONFIG_WED_LISTEN_DURATION; 100 101 /** 102 * Defines the function pointer called on receiving an IEEE 802.15.4 Beacon during an Active Scan. 103 */ 104 typedef otHandleActiveScanResult ActiveScanHandler; 105 106 /** 107 * Defines an Active Scan result. 108 */ 109 typedef otActiveScanResult ActiveScanResult; 110 111 /** 112 * Defines the function pointer which is called during an Energy Scan when the scan result for a channel is 113 * ready or when the scan completes. 114 */ 115 typedef otHandleEnergyScanResult EnergyScanHandler; 116 117 /** 118 * Defines an Energy Scan result. 119 */ 120 typedef otEnergyScanResult EnergyScanResult; 121 122 /** 123 * Implements the IEEE 802.15.4 MAC. 124 */ 125 class Mac : public InstanceLocator, private NonCopyable 126 { 127 friend class ot::Instance; 128 129 public: 130 /** 131 * Initializes the MAC object. 132 * 133 * @param[in] aInstance A reference to the OpenThread instance. 134 */ 135 explicit Mac(Instance &aInstance); 136 137 /** 138 * Starts an IEEE 802.15.4 Active Scan. 139 * 140 * @param[in] aScanChannels A bit vector indicating which channels to scan. Zero is mapped to all channels. 141 * @param[in] aScanDuration The time in milliseconds to spend scanning each channel. Zero duration maps to 142 * default value `kScanDurationDefault` = 300 ms. 143 * @param[in] aHandler A pointer to a function that is called on receiving an IEEE 802.15.4 Beacon. 144 * @param[in] aContext A pointer to an arbitrary context (used when invoking `aHandler` callback). 145 * 146 * @retval kErrorNone Successfully scheduled the Active Scan request. 147 * @retval kErrorBusy Could not schedule the scan (a scan is ongoing or scheduled). 148 */ 149 Error ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext); 150 151 /** 152 * Starts an IEEE 802.15.4 Energy Scan. 153 * 154 * @param[in] aScanChannels A bit vector indicating on which channels to scan. Zero is mapped to all channels. 155 * @param[in] aScanDuration The time in milliseconds to spend scanning each channel. If the duration is set to 156 * zero, a single RSSI sample will be taken per channel. 157 * @param[in] aHandler A pointer to a function called to pass on scan result or indicate scan completion. 158 * @param[in] aContext A pointer to an arbitrary context (used when invoking @p aHandler callback). 159 * 160 * @retval kErrorNone Accepted the Energy Scan request. 161 * @retval kErrorBusy Could not start the energy scan. 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 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 */ IsBeaconEnabled(void) const178 bool IsBeaconEnabled(void) const { return mBeaconsEnabled; } 179 180 /** 181 * Enables/disables IEEE 802.15.4 Beacon transmissions. 182 * 183 * @param[in] aEnabled TRUE to enable IEEE 802.15.4 Beacon transmissions, FALSE otherwise. 184 */ SetBeaconEnabled(bool aEnabled)185 void SetBeaconEnabled(bool aEnabled) { mBeaconsEnabled = aEnabled; } 186 187 /** 188 * Indicates whether or not rx-on-when-idle is enabled. 189 * 190 * @retval TRUE If rx-on-when-idle is enabled. 191 * @retval FALSE If rx-on-when-idle is not enabled. 192 */ GetRxOnWhenIdle(void) const193 bool GetRxOnWhenIdle(void) const { return mRxOnWhenIdle; } 194 195 /** 196 * Sets the rx-on-when-idle mode. 197 * 198 * @param[in] aRxOnWhenIdle The rx-on-when-idle mode. 199 */ 200 void SetRxOnWhenIdle(bool aRxOnWhenIdle); 201 202 /** 203 * Requests a direct data frame transmission. 204 */ 205 void RequestDirectFrameTransmission(void); 206 207 #if OPENTHREAD_FTD 208 /** 209 * Requests an indirect data frame transmission. 210 */ 211 void RequestIndirectFrameTransmission(void); 212 #endif 213 214 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 215 /** 216 * Requests `Mac` to start a CSL tx operation after a delay of @p aDelay time. 217 * 218 * @param[in] aDelay Delay time for `Mac` to start a CSL tx, in units of milliseconds. 219 */ 220 void RequestCslFrameTransmission(uint32_t aDelay); 221 #endif 222 223 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE 224 /** 225 * Requests `Mac` to start a wake-up frame transmission. 226 */ 227 void RequestWakeupFrameTransmission(void); 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 Error RequestDataPollTransmission(void); 237 238 /** 239 * Returns a reference to the IEEE 802.15.4 Extended Address. 240 * 241 * @returns A pointer to the IEEE 802.15.4 Extended Address. 242 */ GetExtAddress(void) const243 const ExtAddress &GetExtAddress(void) const { return mLinks.GetExtAddress(); } 244 245 /** 246 * Sets the IEEE 802.15.4 Extended Address. 247 * 248 * @param[in] aExtAddress A reference to the IEEE 802.15.4 Extended Address. 249 */ SetExtAddress(const ExtAddress & aExtAddress)250 void SetExtAddress(const ExtAddress &aExtAddress) { mLinks.SetExtAddress(aExtAddress); } 251 252 /** 253 * Returns the IEEE 802.15.4 Short Address. 254 * 255 * @returns The IEEE 802.15.4 Short Address. 256 */ GetShortAddress(void) const257 ShortAddress GetShortAddress(void) const { return mLinks.GetShortAddress(); } 258 259 /** 260 * Sets the IEEE 802.15.4 Short Address. 261 * 262 * @param[in] aShortAddress The IEEE 802.15.4 Short Address. 263 */ SetShortAddress(ShortAddress aShortAddress)264 void SetShortAddress(ShortAddress aShortAddress) { mLinks.SetShortAddress(aShortAddress); } 265 266 /** 267 * Gets the alternate short address. 268 * 269 * @returns The alternate short address, or `kShortAddrInvalid` if there is no alternate address. 270 */ GetAlternateShortAddress(void) const271 ShortAddress GetAlternateShortAddress(void) const { return mLinks.GetAlternateShortAddress(); } 272 273 /** 274 * Sets the alternate short address. 275 * 276 * @param[in] aShortAddress The alternate short address. Use `kShortAddrInvalid` to clear the alternate address. 277 */ SetAlternateShortAddress(ShortAddress aShortAddress)278 void SetAlternateShortAddress(ShortAddress aShortAddress) { mLinks.SetAlternateShortAddress(aShortAddress); } 279 280 /** 281 * Returns the IEEE 802.15.4 PAN Channel. 282 * 283 * @returns The IEEE 802.15.4 PAN Channel. 284 */ GetPanChannel(void) const285 uint8_t GetPanChannel(void) const { return mPanChannel; } 286 287 /** 288 * Sets the IEEE 802.15.4 PAN Channel. 289 * 290 * @param[in] aChannel The IEEE 802.15.4 PAN Channel. 291 * 292 * @retval kErrorNone Successfully set the IEEE 802.15.4 PAN Channel. 293 * @retval kErrorInvalidArgs The @p aChannel is not in the supported channel mask. 294 */ 295 Error SetPanChannel(uint8_t aChannel); 296 297 /** 298 * Sets the temporary IEEE 802.15.4 radio channel. 299 * 300 * Allows user to temporarily change the radio channel and use a different channel (during receive) 301 * instead of the PAN channel (from `SetPanChannel()`). A call to `ClearTemporaryChannel()` would clear the 302 * temporary channel and adopt the PAN channel again. The `SetTemporaryChannel()` can be used multiple times in row 303 * (before a call to `ClearTemporaryChannel()`) to change the temporary channel. 304 * 305 * @param[in] aChannel A IEEE 802.15.4 channel. 306 * 307 * @retval kErrorNone Successfully set the temporary channel 308 * @retval kErrorInvalidArgs The @p aChannel is not in the supported channel mask. 309 */ 310 Error SetTemporaryChannel(uint8_t aChannel); 311 312 /** 313 * Clears the use of a previously set temporary channel and adopts the PAN channel. 314 */ 315 void ClearTemporaryChannel(void); 316 317 /** 318 * Returns the supported channel mask. 319 * 320 * @returns The supported channel mask. 321 */ GetSupportedChannelMask(void) const322 const ChannelMask &GetSupportedChannelMask(void) const { return mSupportedChannelMask; } 323 324 /** 325 * Sets the supported channel mask 326 * 327 * @param[in] aMask The supported channel mask. 328 */ 329 void SetSupportedChannelMask(const ChannelMask &aMask); 330 331 /** 332 * Returns the IEEE 802.15.4 PAN ID. 333 * 334 * @returns The IEEE 802.15.4 PAN ID. 335 */ GetPanId(void) const336 PanId GetPanId(void) const { return mPanId; } 337 338 /** 339 * Sets the IEEE 802.15.4 PAN ID. 340 * 341 * @param[in] aPanId The IEEE 802.15.4 PAN ID. 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 */ 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 */ SetMaxFrameRetriesDirect(uint8_t aMaxFrameRetriesDirect)357 void SetMaxFrameRetriesDirect(uint8_t aMaxFrameRetriesDirect) { mMaxFrameRetriesDirect = aMaxFrameRetriesDirect; } 358 359 #if OPENTHREAD_FTD 360 /** 361 * Returns the maximum number of frame retries during indirect transmission. 362 * 363 * @returns The maximum number of retries during indirect transmission. 364 */ GetMaxFrameRetriesIndirect(void) const365 uint8_t GetMaxFrameRetriesIndirect(void) const { return mMaxFrameRetriesIndirect; } 366 367 /** 368 * Sets the maximum number of frame retries during indirect transmission. 369 * 370 * @param[in] aMaxFrameRetriesIndirect The maximum number of retries during indirect transmission. 371 */ SetMaxFrameRetriesIndirect(uint8_t aMaxFrameRetriesIndirect)372 void SetMaxFrameRetriesIndirect(uint8_t aMaxFrameRetriesIndirect) 373 { 374 mMaxFrameRetriesIndirect = aMaxFrameRetriesIndirect; 375 } 376 #endif 377 378 /** 379 * 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 void HandleReceivedFrame(RxFrame *aFrame, Error aError); 386 387 /** 388 * Records CCA status (success/failure) for a frame transmission attempt. 389 * 390 * @param[in] aCcaSuccess TRUE if the CCA succeeded, FALSE otherwise. 391 * @param[in] aChannel The channel on which CCA was performed. 392 */ 393 void RecordCcaStatus(bool aCcaSuccess, uint8_t aChannel); 394 395 /** 396 * Records the status of a frame transmission attempt, updating MAC counters. 397 * 398 * Unlike `HandleTransmitDone` which is called after all transmission attempts of frame to indicate final status 399 * of a frame transmission request, this method is invoked on all frame transmission attempts. 400 * 401 * @param[in] aFrame The transmitted frame. 402 * @param[in] aError kErrorNone when the frame was transmitted successfully, 403 * kErrorNoAck when the frame was transmitted but no ACK was received, 404 * kErrorChannelAccessFailure tx failed due to activity on the channel, 405 * kErrorAbort when transmission was aborted for other reasons. 406 * @param[in] aRetryCount Indicates number of transmission retries for this frame. 407 * @param[in] aWillRetx Indicates whether frame will be retransmitted or not. This is applicable only 408 * when there was an error in transmission (i.e., `aError` is not NONE). 409 */ 410 void RecordFrameTransmitStatus(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx); 411 412 /** 413 * Is called to handle transmit events. 414 * 415 * @param[in] aFrame The frame that was transmitted. 416 * @param[in] aAckFrame A pointer to the ACK frame, `nullptr` if no ACK was received. 417 * @param[in] aError kErrorNone when the frame was transmitted successfully, 418 * kErrorNoAck when the frame was transmitted but no ACK was received, 419 * kErrorChannelAccessFailure when the tx failed due to activity on the channel, 420 * kErrorAbort when transmission was aborted for other reasons. 421 */ 422 void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError); 423 424 /** 425 * Returns if an active scan is in progress. 426 */ IsActiveScanInProgress(void) const427 bool IsActiveScanInProgress(void) const { return IsActiveOrPending(kOperationActiveScan); } 428 429 /** 430 * Returns if an energy scan is in progress. 431 */ IsEnergyScanInProgress(void) const432 bool IsEnergyScanInProgress(void) const { return IsActiveOrPending(kOperationEnergyScan); } 433 434 #if OPENTHREAD_FTD 435 /** 436 * Indicates whether the MAC layer is performing an indirect transmission (in middle of a tx). 437 * 438 * @returns TRUE if in middle of an indirect transmission, FALSE otherwise. 439 */ IsPerformingIndirectTransmit(void) const440 bool IsPerformingIndirectTransmit(void) const { return (mOperation == kOperationTransmitDataIndirect); } 441 #endif 442 443 /** 444 * Returns if the MAC layer is in transmit state. 445 * 446 * The MAC layer is in transmit state during CSMA/CA, CCA, transmission of Data, Beacon or Data Request frames and 447 * receiving of ACK frames. The MAC layer is not in transmit state during transmission of ACK frames or Beacon 448 * Requests. 449 */ 450 bool IsInTransmitState(void) const; 451 452 /** 453 * Registers a callback to provide received raw IEEE 802.15.4 frames. 454 * 455 * @param[in] aPcapCallback A pointer to a function that is called when receiving an IEEE 802.15.4 link frame 456 * or `nullptr` to disable the callback. 457 * @param[in] aCallbackContext A pointer to application-specific context. 458 */ SetPcapCallback(otLinkPcapCallback aPcapCallback,void * aCallbackContext)459 void SetPcapCallback(otLinkPcapCallback aPcapCallback, void *aCallbackContext) 460 { 461 mLinks.SetPcapCallback(aPcapCallback, aCallbackContext); 462 } 463 464 /** 465 * Indicates whether or not promiscuous mode is enabled at the link layer. 466 * 467 * @retval true Promiscuous mode is enabled. 468 * @retval false Promiscuous mode is not enabled. 469 */ IsPromiscuous(void) const470 bool IsPromiscuous(void) const { return mPromiscuous; } 471 472 /** 473 * Enables or disables the link layer promiscuous mode. 474 * 475 * Promiscuous mode keeps the receiver enabled, overriding the value of mRxOnWhenIdle. 476 * 477 * @param[in] aPromiscuous true to enable promiscuous mode, or false otherwise. 478 */ 479 void SetPromiscuous(bool aPromiscuous); 480 481 /** 482 * Resets mac counters 483 */ ResetCounters(void)484 void ResetCounters(void) { ClearAllBytes(mCounters); } 485 486 /** 487 * Returns the MAC counter. 488 * 489 * @returns A reference to the MAC counter. 490 */ GetCounters(void)491 otMacCounters &GetCounters(void) { return mCounters; } 492 493 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 494 /** 495 * Returns the MAC retry histogram for direct transmission. 496 * 497 * @param[out] aNumberOfEntries A reference to where the size of returned histogram array is placed. 498 * 499 * @returns A pointer to the histogram of retries (in a form of an array). 500 * The n-th element indicates that the packet has been sent with n-th retry. 501 */ 502 const uint32_t *GetDirectRetrySuccessHistogram(uint8_t &aNumberOfEntries); 503 504 #if OPENTHREAD_FTD 505 /** 506 * Returns the MAC retry histogram for indirect transmission. 507 * 508 * @param[out] aNumberOfEntries A reference to where the size of returned histogram array is placed. 509 * 510 * @returns A pointer to the histogram of retries (in a form of an array). 511 * The n-th element indicates that the packet has been sent with n-th retry. 512 */ 513 const uint32_t *GetIndirectRetrySuccessHistogram(uint8_t &aNumberOfEntries); 514 #endif 515 516 /** 517 * Resets MAC retry histogram. 518 */ 519 void ResetRetrySuccessHistogram(void); 520 #endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 521 522 /** 523 * Returns the noise floor value (currently use the radio receive sensitivity value). 524 * 525 * @returns The noise floor value in dBm. 526 */ GetNoiseFloor(void) const527 int8_t GetNoiseFloor(void) const { return mLinks.GetNoiseFloor(); } 528 529 /** 530 * Computes the link margin for a given a received signal strength value using noise floor. 531 * 532 * @param[in] aRss The received signal strength in dBm. 533 * 534 * @returns The link margin for @p aRss in dB based on noise floor. 535 */ 536 uint8_t ComputeLinkMargin(int8_t aRss) const; 537 538 /** 539 * Returns the current CCA (Clear Channel Assessment) failure rate. 540 * 541 * The rate is maintained over a window of (roughly) last `OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW` 542 * frame transmissions. 543 * 544 * @returns The CCA failure rate with maximum value `0xffff` corresponding to 100% failure rate. 545 */ GetCcaFailureRate(void) const546 uint16_t GetCcaFailureRate(void) const { return mCcaSuccessRateTracker.GetFailureRate(); } 547 548 /** 549 * Starts/Stops the Link layer. It may only be used when the Netif Interface is down. 550 * 551 * @param[in] aEnable The requested State for the MAC layer. true - Start, false - Stop. 552 */ 553 void SetEnabled(bool aEnable); 554 555 /** 556 * Indicates whether or not the link layer is enabled. 557 * 558 * @retval true Link layer is enabled. 559 * @retval false Link layer is not enabled. 560 */ IsEnabled(void) const561 bool IsEnabled(void) const { return mEnabled; } 562 563 /** 564 * Clears the Mode2Key stored in PSA ITS. 565 */ ClearMode2Key(void)566 void ClearMode2Key(void) { mMode2KeyMaterial.Clear(); } 567 568 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 569 /** 570 * Gets the CSL channel. 571 * 572 * @returns CSL channel. 573 */ GetCslChannel(void) const574 uint8_t GetCslChannel(void) const { return mCslChannel; } 575 576 /** 577 * Sets the CSL channel. 578 * 579 * @param[in] aChannel The CSL channel. 580 */ 581 void SetCslChannel(uint8_t aChannel); 582 583 /** 584 * Centralizes CSL state switching conditions evaluating, configuring SubMac accordingly. 585 */ 586 void UpdateCsl(void); 587 588 /** 589 * Gets the CSL period. 590 * 591 * @returns CSL period in units of 10 symbols. 592 */ GetCslPeriod(void) const593 uint16_t GetCslPeriod(void) const { return mCslPeriod; } 594 595 /** 596 * Gets the CSL period in milliseconds. 597 * 598 * If the CSL period cannot be represented exactly in milliseconds, return the rounded value to the nearest 599 * millisecond. 600 * 601 * @returns CSL period in milliseconds. 602 */ 603 uint32_t GetCslPeriodInMsec(void) const; 604 605 /** 606 * Sets the CSL period. 607 * 608 * @param[in] aPeriod The CSL period in 10 symbols. 609 */ 610 void SetCslPeriod(uint16_t aPeriod); 611 612 /** 613 * This method converts a given CSL period in units of 10 symbols to microseconds. 614 * 615 * @param[in] aPeriodInTenSymbols The CSL period in unit of 10 symbols. 616 * 617 * @returns The converted CSL period value in microseconds corresponding to @p aPeriodInTenSymbols. 618 */ 619 static uint32_t CslPeriodToUsec(uint16_t aPeriodInTenSymbols); 620 621 /** 622 * Indicates whether CSL is started at the moment. 623 * 624 * @retval TRUE If CSL is enabled. 625 * @retval FALSE If CSL is not enabled. 626 */ 627 bool IsCslEnabled(void) const; 628 629 /** 630 * Indicates whether Link is capable of starting CSL. 631 * 632 * @retval TRUE If Link is capable of starting CSL. 633 * @retval FALSE If link is not capable of starting CSL. 634 */ 635 bool IsCslCapable(void) const; 636 637 /** 638 * Indicates whether the device is connected to a parent which supports CSL. 639 * 640 * @retval TRUE If parent supports CSL. 641 * @retval FALSE If parent does not support CSL. 642 */ 643 bool IsCslSupported(void) const; 644 645 /** 646 * Returns parent CSL accuracy (clock accuracy and uncertainty). 647 * 648 * @returns The parent CSL accuracy. 649 */ GetCslParentAccuracy(void) const650 const CslAccuracy &GetCslParentAccuracy(void) const { return mLinks.GetSubMac().GetCslParentAccuracy(); } 651 652 /** 653 * Sets parent CSL accuracy. 654 * 655 * @param[in] aCslAccuracy The parent CSL accuracy. 656 */ SetCslParentAccuracy(const CslAccuracy & aCslAccuracy)657 void SetCslParentAccuracy(const CslAccuracy &aCslAccuracy) 658 { 659 mLinks.GetSubMac().SetCslParentAccuracy(aCslAccuracy); 660 } 661 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 662 663 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE 664 /** 665 * Enables/disables the 802.15.4 radio filter. 666 * 667 * When radio filter is enabled, radio is put to sleep instead of receive (to ensure device does not receive any 668 * frame and/or potentially send ack). Also the frame transmission requests return immediately without sending the 669 * frame over the air (return "no ack" error if ack is requested, otherwise return success). 670 * 671 * @param[in] aFilterEnabled TRUE to enable radio filter, FALSE to disable. 672 */ 673 void SetRadioFilterEnabled(bool aFilterEnabled); 674 675 /** 676 * Indicates whether the 802.15.4 radio filter is enabled or not. 677 * 678 * @retval TRUE If the radio filter is enabled. 679 * @retval FALSE If the radio filter is disabled. 680 */ IsRadioFilterEnabled(void) const681 bool IsRadioFilterEnabled(void) const { return mLinks.GetSubMac().IsRadioFilterEnabled(); } 682 #endif 683 684 /** 685 * Sets the region code. 686 * 687 * The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code. 688 * 689 * @param[in] aRegionCode The radio region code. The `aRegionCode >> 8` is first ascii char 690 * and the `aRegionCode & 0xff` is the second ascii char. 691 * 692 * @retval kErrorFailed Other platform specific errors. 693 * @retval kErrorNone Successfully set region code. 694 * @retval kErrorNotImplemented The feature is not implemented. 695 */ 696 Error SetRegion(uint16_t aRegionCode); 697 698 /** 699 * Get the region code. 700 * 701 * The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code. 702 * 703 * @param[out] aRegionCode The radio region code. The `aRegionCode >> 8` is first ascii char 704 * and the `aRegionCode & 0xff` is the second ascii char. 705 * 706 * @retval kErrorFailed Other platform specific errors. 707 * @retval kErrorNone Successfully set region code. 708 * @retval kErrorNotImplemented The feature is not implemented. 709 */ 710 Error GetRegion(uint16_t &aRegionCode) const; 711 712 /** 713 * Gets the wake-up channel. 714 * 715 * @returns wake-up channel. 716 */ GetWakeupChannel(void) const717 uint8_t GetWakeupChannel(void) const { return mWakeupChannel; } 718 719 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 720 /** 721 * Sets the wake-up channel. 722 * 723 * @param[in] aChannel The wake-up channel. 724 * 725 * @retval kErrorNone Successfully set the wake-up channel. 726 * @retval kErrorInvalidArgs The @p aChannel is not in the supported channel mask. 727 */ 728 Error SetWakeupChannel(uint8_t aChannel); 729 #endif 730 731 #if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 732 /** 733 * Gets the wake-up listen parameters. 734 * 735 * @param[out] aInterval A reference to return the wake-up listen interval in microseconds. 736 * @param[out] aDuration A reference to return the wake-up listen duration in microseconds. 737 */ 738 void GetWakeupListenParameters(uint32_t &aInterval, uint32_t &aDuration) const; 739 740 /** 741 * Sets the wake-up listen parameters. 742 * 743 * The listen interval must be greater than the listen duration. 744 * The listen duration must be greater or equal than `kMinWakeupListenDuration`. 745 * 746 * @param[in] aInterval The wake-up listen interval in microseconds. 747 * @param[in] aDuration The wake-up listen duration in microseconds. 748 * 749 * @retval kErrorNone Successfully set the wake-up listen parameters. 750 * @retval kErrorInvalidArgs Configured listen interval is not greater than listen duration. 751 */ 752 Error SetWakeupListenParameters(uint32_t aInterval, uint32_t aDuration); 753 754 /** 755 * Enables/disables listening for wake-up frames. 756 * 757 * @param[in] aEnable TRUE to enable listening for wake-up frames, FALSE otherwise 758 * 759 * @retval kErrorNone Successfully enabled/disabled listening for wake-up frames. 760 * @retval kErrorInvalidArgs Configured listen interval is not greater than listen duration. 761 * @retval kErrorInvalidState Could not enable/disable listening for wake-up frames. 762 */ 763 Error SetWakeupListenEnabled(bool aEnable); 764 765 /** 766 * Returns whether listening for wake-up frames is enabled. 767 * 768 * @retval TRUE If listening for wake-up frames is enabled. 769 * @retval FALSE If listening for wake-up frames is not enabled. 770 */ IsWakeupListenEnabled(void) const771 bool IsWakeupListenEnabled(void) const { return mWakeupListenEnabled; } 772 #endif // OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 773 774 /** 775 * Calculates the radio bus transfer time (in microseconds) for a given frame size based on `Radio::GetBusSpeed()` 776 * and `Radio::GetBusLatency()`. 777 * 778 * @param[in] aFrameSize The frame size to calculate for, in bytes. 779 * 780 * @returns The calculated radio bus transfer time in microseconds. 781 */ 782 uint32_t CalculateRadioBusTransferTime(uint16_t aFrameSize) const; 783 784 private: 785 static constexpr uint16_t kMaxCcaSampleCount = OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW; 786 787 enum Operation : uint8_t 788 { 789 kOperationIdle = 0, 790 kOperationActiveScan, 791 kOperationEnergyScan, 792 kOperationTransmitBeacon, 793 kOperationTransmitDataDirect, 794 kOperationTransmitPoll, 795 kOperationWaitingForData, 796 #if OPENTHREAD_FTD 797 kOperationTransmitDataIndirect, 798 #endif 799 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 800 kOperationTransmitDataCsl, 801 #endif 802 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE 803 kOperationTransmitWakeup, 804 #endif 805 }; 806 807 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 808 struct RetryHistogram 809 { 810 /** 811 * Histogram of number of retries for a single direct packet until success 812 * [0 retry: packet count, 1 retry: packet count, 2 retry : packet count ... 813 * until max retry limit: packet count] 814 * 815 * The size of the array is OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_DIRECT. 816 */ 817 uint32_t mTxDirectRetrySuccess[OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_DIRECT]; 818 819 /** 820 * Histogram of number of retries for a single indirect packet until success 821 * [0 retry: packet count, 1 retry: packet count, 2 retry : packet count ... 822 * until max retry limit: packet count] 823 * 824 * The size of the array is OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_INDIRECT. 825 */ 826 uint32_t mTxIndirectRetrySuccess[OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_INDIRECT]; 827 }; 828 #endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 829 830 Error ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor); 831 void ProcessTransmitSecurity(TxFrame &aFrame); 832 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 833 Error ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame); 834 #endif 835 836 void UpdateIdleMode(void); IsPending(Operation aOperation) const837 bool IsPending(Operation aOperation) const { return mPendingOperations & (1U << aOperation); } 838 bool IsActiveOrPending(Operation aOperation) const; SetPending(Operation aOperation)839 void SetPending(Operation aOperation) { mPendingOperations |= (1U << aOperation); } ClearPending(Operation aOperation)840 void ClearPending(Operation aOperation) { mPendingOperations &= ~(1U << aOperation); } 841 void StartOperation(Operation aOperation); 842 void FinishOperation(void); 843 void PerformNextOperation(void); 844 TxFrame *PrepareBeaconRequest(void); 845 TxFrame *PrepareBeacon(void); 846 bool ShouldSendBeacon(void) const; 847 bool IsJoinable(void) const; 848 void BeginTransmit(void); 849 Error FilterDestShortAddress(ShortAddress aDestAddress) const; 850 void UpdateNeighborLinkInfo(Neighbor &aNeighbor, const RxFrame &aRxFrame); 851 bool HandleMacCommand(RxFrame &aFrame); 852 void HandleTimer(void); 853 854 void Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanDuration); 855 Error UpdateScanChannel(void); 856 void PerformActiveScan(void); 857 void ReportActiveScanResult(const RxFrame *aBeaconFrame); 858 Error ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult); 859 void PerformEnergyScan(void); 860 void ReportEnergyScanResult(int8_t aRssi); 861 862 void LogFrameRxFailure(const RxFrame *aFrame, Error aError) const; 863 void LogFrameTxFailure(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx) const; 864 void LogBeacon(const char *aActionText) const; 865 866 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 867 uint8_t GetTimeIeOffset(const Frame &aFrame); 868 #endif 869 870 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 871 void ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr); 872 #endif 873 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 874 void ProcessEnhAckProbing(const RxFrame &aFrame, const Neighbor &aNeighbor); 875 #endif 876 #if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 877 Error HandleWakeupFrame(const RxFrame &aFrame); 878 void UpdateWakeupListening(void); 879 #endif 880 static const char *OperationToString(Operation aOperation); 881 882 using OperationTask = TaskletIn<Mac, &Mac::PerformNextOperation>; 883 using MacTimer = TimerMilliIn<Mac, &Mac::HandleTimer>; 884 885 static const otExtAddress sMode2ExtAddress; 886 887 bool mEnabled : 1; 888 bool mShouldTxPollBeforeData : 1; 889 bool mRxOnWhenIdle : 1; 890 bool mPromiscuous : 1; 891 bool mBeaconsEnabled : 1; 892 bool mUsingTemporaryChannel : 1; 893 #if OPENTHREAD_CONFIG_MAC_STAY_AWAKE_BETWEEN_FRAGMENTS 894 bool mShouldDelaySleep : 1; 895 bool mDelayingSleep : 1; 896 #endif 897 #if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 898 bool mWakeupListenEnabled : 1; 899 #endif 900 Operation mOperation; 901 uint16_t mPendingOperations; 902 uint8_t mBeaconSequence; 903 uint8_t mDataSequence; 904 uint8_t mBroadcastTransmitCount; 905 PanId mPanId; 906 uint8_t mPanChannel; 907 uint8_t mRadioChannel; 908 ChannelMask mSupportedChannelMask; 909 uint8_t mScanChannel; 910 uint16_t mScanDuration; 911 ChannelMask mScanChannelMask; 912 uint8_t mMaxFrameRetriesDirect; 913 #if OPENTHREAD_FTD 914 uint8_t mMaxFrameRetriesIndirect; 915 #endif 916 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 917 TimeMilli mCslTxFireTime; 918 #endif 919 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 920 // When Mac::mCslChannel is 0, it indicates that CSL channel has not been specified by the upper layer. 921 uint8_t mCslChannel; 922 uint16_t mCslPeriod; 923 #endif 924 uint8_t mWakeupChannel; 925 #if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 926 uint32_t mWakeupListenInterval; 927 uint32_t mWakeupListenDuration; 928 #endif 929 union 930 { 931 ActiveScanHandler mActiveScanHandler; 932 EnergyScanHandler mEnergyScanHandler; 933 }; 934 935 void *mScanHandlerContext; 936 937 Links mLinks; 938 OperationTask mOperationTask; 939 MacTimer mTimer; 940 otMacCounters mCounters; 941 uint32_t mKeyIdMode2FrameCounter; 942 SuccessRateTracker mCcaSuccessRateTracker; 943 uint16_t mCcaSampleCount; 944 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 945 RetryHistogram mRetryHistogram; 946 #endif 947 948 #if OPENTHREAD_CONFIG_MULTI_RADIO 949 RadioTypes mTxPendingRadioLinks; 950 RadioTypes mTxBeaconRadioLinks; 951 Error mTxError; 952 #endif 953 954 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE 955 Filter mFilter; 956 #endif 957 958 KeyMaterial mMode2KeyMaterial; 959 }; 960 961 /** 962 * @} 963 */ 964 965 } // namespace Mac 966 } // namespace ot 967 968 #endif // MAC_HPP_ 969