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/non_copyable.hpp" 44 #include "common/tasklet.hpp" 45 #include "common/time.hpp" 46 #include "common/timer.hpp" 47 #include "mac/channel_mask.hpp" 48 #include "mac/mac_filter.hpp" 49 #include "mac/mac_frame.hpp" 50 #include "mac/mac_links.hpp" 51 #include "mac/mac_types.hpp" 52 #include "mac/sub_mac.hpp" 53 #include "radio/trel_link.hpp" 54 #include "thread/key_manager.hpp" 55 #include "thread/link_quality.hpp" 56 57 namespace ot { 58 59 class Neighbor; 60 61 /** 62 * @addtogroup core-mac 63 * 64 * @brief 65 * This module includes definitions for the IEEE 802.15.4 MAC 66 * 67 * @{ 68 * 69 */ 70 71 namespace Mac { 72 73 constexpr uint32_t kDataPollTimeout = 100; ///< Timeout for receiving Data Frame (in msec). 74 constexpr uint32_t kSleepDelay = 300; ///< Max sleep delay when frame is pending (in msec). 75 76 constexpr uint16_t kScanDurationDefault = OPENTHREAD_CONFIG_MAC_SCAN_DURATION; ///< Duration per channel (in msec). 77 78 constexpr uint8_t kMaxCsmaBackoffsDirect = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT; 79 constexpr uint8_t kMaxCsmaBackoffsIndirect = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_INDIRECT; 80 constexpr uint8_t kMaxCsmaBackoffsCsl = 0; 81 82 constexpr uint8_t kDefaultMaxFrameRetriesDirect = OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT; 83 constexpr uint8_t kDefaultMaxFrameRetriesIndirect = OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_INDIRECT; 84 constexpr uint8_t kMaxFrameRetriesCsl = 0; 85 86 constexpr uint8_t kTxNumBcast = OPENTHREAD_CONFIG_MAC_TX_NUM_BCAST; ///< Num of times broadcast frame is tx. 87 88 /** 89 * This type defines the function pointer called on receiving an IEEE 802.15.4 Beacon during an Active Scan. 90 * 91 */ 92 typedef otHandleActiveScanResult ActiveScanHandler; 93 94 /** 95 * This type defines an Active Scan result. 96 * 97 */ 98 typedef otActiveScanResult ActiveScanResult; 99 100 /** 101 * This type defines the function pointer which is called during an Energy Scan when the scan result for a channel is 102 * ready or when the scan completes. 103 * 104 */ 105 typedef otHandleEnergyScanResult EnergyScanHandler; 106 107 /** 108 * This type defines an Energy Scan result. 109 * 110 */ 111 typedef otEnergyScanResult EnergyScanResult; 112 113 /** 114 * This class implements the IEEE 802.15.4 MAC. 115 * 116 */ 117 class Mac : public InstanceLocator, private NonCopyable 118 { 119 friend class ot::Instance; 120 121 public: 122 /** 123 * This constructor initializes the MAC object. 124 * 125 * @param[in] aInstance A reference to the OpenThread instance. 126 * 127 */ 128 explicit Mac(Instance &aInstance); 129 130 /** 131 * This method starts an IEEE 802.15.4 Active Scan. 132 * 133 * @param[in] aScanChannels A bit vector indicating which channels to scan. Zero is mapped to all channels. 134 * @param[in] aScanDuration The time in milliseconds to spend scanning each channel. Zero duration maps to 135 * default value `kScanDurationDefault` = 300 ms. 136 * @param[in] aHandler A pointer to a function that is called on receiving an IEEE 802.15.4 Beacon. 137 * @param[in] aContext A pointer to an arbitrary context (used when invoking `aHandler` callback). 138 * 139 * @retval kErrorNone Successfully scheduled the Active Scan request. 140 * @retval kErrorBusy Could not schedule the scan (a scan is ongoing or scheduled). 141 * 142 */ 143 Error ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext); 144 145 /** 146 * This method starts an IEEE 802.15.4 Energy Scan. 147 * 148 * @param[in] aScanChannels A bit vector indicating on which channels to scan. Zero is mapped to all channels. 149 * @param[in] aScanDuration The time in milliseconds to spend scanning each channel. If the duration is set to 150 * zero, a single RSSI sample will be taken per channel. 151 * @param[in] aHandler A pointer to a function called to pass on scan result or indicate scan completion. 152 * @param[in] aContext A pointer to an arbitrary context (used when invoking @p aHandler callback). 153 * 154 * @retval kErrorNone Accepted the Energy Scan request. 155 * @retval kErrorBusy Could not start the energy scan. 156 * 157 */ 158 Error EnergyScan(uint32_t aScanChannels, uint16_t aScanDuration, EnergyScanHandler aHandler, void *aContext); 159 160 /** 161 * This method indicates the energy scan for the current channel is complete. 162 * 163 * @param[in] aEnergyScanMaxRssi The maximum RSSI encountered on the scanned channel. 164 * 165 */ 166 void EnergyScanDone(int8_t aEnergyScanMaxRssi); 167 168 /** 169 * This method indicates whether or not IEEE 802.15.4 Beacon transmissions are enabled. 170 * 171 * @retval TRUE If IEEE 802.15.4 Beacon transmissions are enabled. 172 * @retval FALSE If IEEE 802.15.4 Beacon transmissions are not enabled. 173 * 174 */ IsBeaconEnabled(void) const175 bool IsBeaconEnabled(void) const { return mBeaconsEnabled; } 176 177 /** 178 * This method enables/disables IEEE 802.15.4 Beacon transmissions. 179 * 180 * @param[in] aEnabled TRUE to enable IEEE 802.15.4 Beacon transmissions, FALSE otherwise. 181 * 182 */ SetBeaconEnabled(bool aEnabled)183 void SetBeaconEnabled(bool aEnabled) { mBeaconsEnabled = aEnabled; } 184 185 /** 186 * This method indicates whether or not rx-on-when-idle is enabled. 187 * 188 * @retval TRUE If rx-on-when-idle is enabled. 189 * @retval FALSE If rx-on-when-idle is not enabled. 190 */ GetRxOnWhenIdle(void) const191 bool GetRxOnWhenIdle(void) const { return mRxOnWhenIdle; } 192 193 /** 194 * This method sets the rx-on-when-idle mode. 195 * 196 * @param[in] aRxOnWhenIdle The rx-on-when-idle mode. 197 * 198 */ 199 void SetRxOnWhenIdle(bool aRxOnWhenIdle); 200 201 /** 202 * This method requests a direct data frame transmission. 203 * 204 */ 205 void RequestDirectFrameTransmission(void); 206 207 #if OPENTHREAD_FTD 208 /** 209 * This method requests an indirect data frame transmission. 210 * 211 */ 212 void RequestIndirectFrameTransmission(void); 213 214 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 215 /** 216 * This method 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 */ 221 void RequestCslFrameTransmission(uint32_t aDelay); 222 #endif 223 224 #endif 225 226 /** 227 * This method requests transmission of a data poll (MAC Data Request) frame. 228 * 229 * @retval kErrorNone Data poll transmission request is scheduled successfully. 230 * @retval kErrorAlready MAC is busy sending earlier poll transmission request. 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 Network Name. 327 * 328 * @returns The IEEE 802.15.4 Network Name. 329 * 330 */ GetNetworkName(void) const331 const NetworkName &GetNetworkName(void) const { return mNetworkName; } 332 333 /** 334 * This method sets the IEEE 802.15.4 Network Name. 335 * 336 * @param[in] aNameString A pointer to a string character array. Must be null terminated. 337 * 338 * @retval kErrorNone Successfully set the IEEE 802.15.4 Network Name. 339 * @retval kErrorInvalidArgs Given name is too long. 340 * 341 */ 342 Error SetNetworkName(const char *aNameString); 343 344 /** 345 * This method sets the IEEE 802.15.4 Network Name. 346 * 347 * @param[in] aNameData A name data (pointer to char buffer and length). 348 * 349 * @retval kErrorNone Successfully set the IEEE 802.15.4 Network Name. 350 * @retval kErrorInvalidArgs Given name is too long. 351 * 352 */ 353 Error SetNetworkName(const NameData &aNameData); 354 355 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) 356 /** 357 * This method returns the Thread Domain Name. 358 * 359 * @returns The Thread Domain Name. 360 * 361 */ GetDomainName(void) const362 const DomainName &GetDomainName(void) const { return mDomainName; } 363 364 /** 365 * This method sets the Thread Domain Name. 366 * 367 * @param[in] aNameString A pointer to a string character array. Must be null terminated. 368 * 369 * @retval kErrorNone Successfully set the Thread Domain Name. 370 * @retval kErrorInvalidArgs Given name is too long. 371 * 372 */ 373 Error SetDomainName(const char *aNameString); 374 375 /** 376 * This method sets the Thread Domain Name. 377 * 378 * @param[in] aNameData A name data (pointer to char buffer and length). 379 * 380 * @retval kErrorNone Successfully set the Thread Domain Name. 381 * @retval kErrorInvalidArgs Given name is too long. 382 * 383 */ 384 Error SetDomainName(const NameData &aNameData); 385 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) 386 387 /** 388 * This method returns the IEEE 802.15.4 PAN ID. 389 * 390 * @returns The IEEE 802.15.4 PAN ID. 391 * 392 */ GetPanId(void) const393 PanId GetPanId(void) const { return mPanId; } 394 395 /** 396 * This method sets the IEEE 802.15.4 PAN ID. 397 * 398 * @param[in] aPanId The IEEE 802.15.4 PAN ID. 399 * 400 */ 401 void SetPanId(PanId aPanId); 402 403 /** 404 * This method returns the IEEE 802.15.4 Extended PAN Identifier. 405 * 406 * @returns The IEEE 802.15.4 Extended PAN Identifier. 407 * 408 */ GetExtendedPanId(void) const409 const ExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; } 410 411 /** 412 * This method sets the IEEE 802.15.4 Extended PAN Identifier. 413 * 414 * @param[in] aExtendedPanId The IEEE 802.15.4 Extended PAN Identifier. 415 * 416 */ 417 void SetExtendedPanId(const ExtendedPanId &aExtendedPanId); 418 419 /** 420 * This method returns the maximum number of frame retries during direct transmission. 421 * 422 * @returns The maximum number of retries during direct transmission. 423 * 424 */ GetMaxFrameRetriesDirect(void) const425 uint8_t GetMaxFrameRetriesDirect(void) const { return mMaxFrameRetriesDirect; } 426 427 /** 428 * This method sets the maximum number of frame retries during direct transmission. 429 * 430 * @param[in] aMaxFrameRetriesDirect The maximum number of retries during direct transmission. 431 * 432 */ SetMaxFrameRetriesDirect(uint8_t aMaxFrameRetriesDirect)433 void SetMaxFrameRetriesDirect(uint8_t aMaxFrameRetriesDirect) { mMaxFrameRetriesDirect = aMaxFrameRetriesDirect; } 434 435 #if OPENTHREAD_FTD 436 /** 437 * This method returns the maximum number of frame retries during indirect transmission. 438 * 439 * @returns The maximum number of retries during indirect transmission. 440 * 441 */ GetMaxFrameRetriesIndirect(void) const442 uint8_t GetMaxFrameRetriesIndirect(void) const { return mMaxFrameRetriesIndirect; } 443 444 /** 445 * This method sets the maximum number of frame retries during indirect transmission. 446 * 447 * @param[in] aMaxFrameRetriesIndirect The maximum number of retries during indirect transmission. 448 * 449 */ SetMaxFrameRetriesIndirect(uint8_t aMaxFrameRetriesIndirect)450 void SetMaxFrameRetriesIndirect(uint8_t aMaxFrameRetriesIndirect) 451 { 452 mMaxFrameRetriesIndirect = aMaxFrameRetriesIndirect; 453 } 454 #endif 455 456 /** 457 * This method is called to handle a received frame. 458 * 459 * @param[in] aFrame A pointer to the received frame, or nullptr if the receive operation was aborted. 460 * @param[in] aError kErrorNone when successfully received a frame, 461 * kErrorAbort when reception was aborted and a frame was not received. 462 * 463 */ 464 void HandleReceivedFrame(RxFrame *aFrame, Error aError); 465 466 /** 467 * This method records CCA status (success/failure) for a frame transmission attempt. 468 * 469 * @param[in] aCcaSuccess TRUE if the CCA succeeded, FALSE otherwise. 470 * @param[in] aChannel The channel on which CCA was performed. 471 * 472 */ 473 void RecordCcaStatus(bool aCcaSuccess, uint8_t aChannel); 474 475 /** 476 * This method records the status of a frame transmission attempt, updating MAC counters. 477 * 478 * Unlike `HandleTransmitDone` which is called after all transmission attempts of frame to indicate final status 479 * of a frame transmission request, this method is invoked on all frame transmission attempts. 480 * 481 * @param[in] aFrame The transmitted frame. 482 * @param[in] aAckFrame A pointer to the ACK frame, or nullptr if no ACK was received. 483 * @param[in] aError kErrorNone when the frame was transmitted successfully, 484 * kErrorNoAck when the frame was transmitted but no ACK was received, 485 * kErrorChannelAccessFailure tx failed due to activity on the channel, 486 * kErrorAbort when transmission was aborted for other reasons. 487 * @param[in] aRetryCount Indicates number of transmission retries for this frame. 488 * @param[in] aWillRetx Indicates whether frame will be retransmitted or not. This is applicable only 489 * when there was an error in transmission (i.e., `aError` is not NONE). 490 * 491 */ 492 void RecordFrameTransmitStatus(const TxFrame &aFrame, 493 const RxFrame *aAckFrame, 494 Error aError, 495 uint8_t aRetryCount, 496 bool aWillRetx); 497 498 /** 499 * This method is called to handle transmit events. 500 * 501 * @param[in] aFrame The frame that was transmitted. 502 * @param[in] aAckFrame A pointer to the ACK frame, nullptr if no ACK was received. 503 * @param[in] aError kErrorNone when the frame was transmitted successfully, 504 * kErrorNoAck when the frame was transmitted but no ACK was received, 505 * kErrorChannelAccessFailure when the tx failed due to activity on the channel, 506 * kErrorAbort when transmission was aborted for other reasons. 507 * 508 */ 509 void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError); 510 511 /** 512 * This method returns if an active scan is in progress. 513 * 514 */ IsActiveScanInProgress(void) const515 bool IsActiveScanInProgress(void) const { return (mOperation == kOperationActiveScan) || (mPendingActiveScan); } 516 517 /** 518 * This method returns if an energy scan is in progress. 519 * 520 */ IsEnergyScanInProgress(void) const521 bool IsEnergyScanInProgress(void) const { return (mOperation == kOperationEnergyScan) || (mPendingEnergyScan); } 522 523 #if OPENTHREAD_FTD 524 /** 525 * This method indicates whether the MAC layer is performing an indirect transmission (in middle of a tx). 526 * 527 * @returns TRUE if in middle of an indirect transmission, FALSE otherwise. 528 * 529 */ IsPerformingIndirectTransmit(void) const530 bool IsPerformingIndirectTransmit(void) const { return (mOperation == kOperationTransmitDataIndirect); } 531 #endif 532 533 /** 534 * This method returns if the MAC layer is in transmit state. 535 * 536 * The MAC layer is in transmit state during CSMA/CA, CCA, transmission of Data, Beacon or Data Request frames and 537 * receiving of ACK frames. The MAC layer is not in transmit state during transmission of ACK frames or Beacon 538 * Requests. 539 * 540 */ 541 bool IsInTransmitState(void) const; 542 543 /** 544 * This method registers a callback to provide received raw IEEE 802.15.4 frames. 545 * 546 * @param[in] aPcapCallback A pointer to a function that is called when receiving an IEEE 802.15.4 link frame 547 * or nullptr to disable the callback. 548 * @param[in] aCallbackContext A pointer to application-specific context. 549 * 550 */ SetPcapCallback(otLinkPcapCallback aPcapCallback,void * aCallbackContext)551 void SetPcapCallback(otLinkPcapCallback aPcapCallback, void *aCallbackContext) 552 { 553 mLinks.SetPcapCallback(aPcapCallback, aCallbackContext); 554 } 555 556 /** 557 * This method indicates whether or not promiscuous mode is enabled at the link layer. 558 * 559 * @retval true Promiscuous mode is enabled. 560 * @retval false Promiscuous mode is not enabled. 561 * 562 */ IsPromiscuous(void) const563 bool IsPromiscuous(void) const { return mPromiscuous; } 564 565 /** 566 * This method enables or disables the link layer promiscuous mode. 567 * 568 * Promiscuous mode keeps the receiver enabled, overriding the value of mRxOnWhenIdle. 569 * 570 * @param[in] aPromiscuous true to enable promiscuous mode, or false otherwise. 571 * 572 */ 573 void SetPromiscuous(bool aPromiscuous); 574 575 /** 576 * This method resets mac counters 577 * 578 */ ResetCounters(void)579 void ResetCounters(void) { memset(&mCounters, 0, sizeof(mCounters)); } 580 581 /** 582 * This method returns the MAC counter. 583 * 584 * @returns A reference to the MAC counter. 585 * 586 */ GetCounters(void)587 otMacCounters &GetCounters(void) { return mCounters; } 588 589 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 590 /** 591 * This method returns the MAC retry histogram for direct transmission. 592 * 593 * @param[out] aNumberOfEntries A reference to where the size of returned histogram array is placed. 594 * 595 * @returns A pointer to the histogram of retries (in a form of an array). 596 * The n-th element indicates that the packet has been sent with n-th retry. 597 * 598 */ 599 const uint32_t *GetDirectRetrySuccessHistogram(uint8_t &aNumberOfEntries); 600 601 #if OPENTHREAD_FTD 602 /** 603 * This method returns the MAC retry histogram for indirect transmission. 604 * 605 * @param[out] aNumberOfEntries A reference to where the size of returned histogram array is placed. 606 * 607 * @returns A pointer to the histogram of retries (in a form of an array). 608 * The n-th element indicates that the packet has been sent with n-th retry. 609 * 610 */ 611 const uint32_t *GetIndirectRetrySuccessHistogram(uint8_t &aNumberOfEntries); 612 #endif 613 614 /** 615 * This method resets MAC retry histogram. 616 * 617 */ 618 void ResetRetrySuccessHistogram(void); 619 #endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 620 621 /** 622 * This method returns the noise floor value (currently use the radio receive sensitivity value). 623 * 624 * @returns The noise floor value in dBm. 625 * 626 */ GetNoiseFloor(void)627 int8_t GetNoiseFloor(void) { return mLinks.GetNoiseFloor(); } 628 629 /** 630 * This method returns the current CCA (Clear Channel Assessment) failure rate. 631 * 632 * The rate is maintained over a window of (roughly) last `OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW` 633 * frame transmissions. 634 * 635 * @returns The CCA failure rate with maximum value `0xffff` corresponding to 100% failure rate. 636 * 637 */ GetCcaFailureRate(void) const638 uint16_t GetCcaFailureRate(void) const { return mCcaSuccessRateTracker.GetFailureRate(); } 639 640 /** 641 * This method Starts/Stops the Link layer. It may only be used when the Netif Interface is down. 642 * 643 * @param[in] aEnable The requested State for the MAC layer. true - Start, false - Stop. 644 * 645 */ SetEnabled(bool aEnable)646 void SetEnabled(bool aEnable) { mEnabled = aEnable; } 647 648 /** 649 * This method indicates whether or not the link layer is enabled. 650 * 651 * @retval true Link layer is enabled. 652 * @retval false Link layer is not enabled. 653 * 654 */ IsEnabled(void) const655 bool IsEnabled(void) const { return mEnabled; } 656 657 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 658 /** 659 * This method gets the CSL channel. 660 * 661 * @returns CSL channel. 662 * 663 */ GetCslChannel(void) const664 uint8_t GetCslChannel(void) const { return mLinks.GetSubMac().GetCslChannel(); } 665 666 /** 667 * This method sets the CSL channel. 668 * 669 * @param[in] aChannel The CSL channel. 670 * 671 */ 672 void SetCslChannel(uint8_t aChannel); 673 674 /** 675 * This method indicates if CSL channel has been explicitly specified by the upper layer. 676 * 677 * @returns If CSL channel has been specified. 678 * 679 */ IsCslChannelSpecified(void) const680 bool IsCslChannelSpecified(void) const { return mLinks.GetSubMac().IsCslChannelSpecified(); } 681 682 /** 683 * This method gets the CSL period. 684 * 685 * @returns CSL period in units of 10 symbols. 686 * 687 */ GetCslPeriod(void) const688 uint16_t GetCslPeriod(void) const { return mLinks.GetSubMac().GetCslPeriod(); } 689 690 /** 691 * This method sets the CSL period. 692 * 693 * @param[in] aPeriod The CSL period in 10 symbols. 694 * 695 */ 696 void SetCslPeriod(uint16_t aPeriod); 697 698 /** 699 * This method indicates whether CSL is started at the moment. 700 * 701 * @retval TRUE If CSL is enabled. 702 * @retval FALSE If CSL is not enabled. 703 * 704 */ 705 bool IsCslEnabled(void) const; 706 707 /** 708 * This method indicates whether Link is capable of starting CSL. 709 * 710 * @retval TRUE If Link is capable of starting CSL. 711 * @retval FALSE If link is not capable of starting CSL. 712 * 713 */ 714 bool IsCslCapable(void) const; 715 716 /** 717 * This method returns CSL parent clock accuracy, in ± ppm. 718 * 719 * @retval CSL parent clock accuracy, in ± ppm. 720 * 721 */ GetCslParentClockAccuracy(void) const722 uint8_t GetCslParentClockAccuracy(void) const { return mLinks.GetSubMac().GetCslParentClockAccuracy(); } 723 724 /** 725 * This method sets CSL parent clock accuracy, in ± ppm. 726 * 727 * @param[in] aCslParentAccuracy CSL parent clock accuracy, in ± ppm. 728 * 729 */ SetCslParentClockAccuracy(uint8_t aCslParentAccuracy)730 void SetCslParentClockAccuracy(uint8_t aCslParentAccuracy) 731 { 732 mLinks.GetSubMac().SetCslParentClockAccuracy(aCslParentAccuracy); 733 } 734 735 /** 736 * This method returns CSL parent uncertainty, in ±10 us units. 737 * 738 * @retval CSL parent uncertainty, in ±10 us units. 739 * 740 */ GetCslParentUncertainty(void) const741 uint8_t GetCslParentUncertainty(void) const { return mLinks.GetSubMac().GetCslParentUncertainty(); } 742 743 /** 744 * This method returns CSL parent uncertainty, in ±10 us units. 745 * 746 * @param[in] aCslParentUncert CSL parent uncertainty, in ±10 us units. 747 * 748 */ SetCslParentUncertainty(uint8_t aCslParentUncert)749 void SetCslParentUncertainty(uint8_t aCslParentUncert) 750 { 751 mLinks.GetSubMac().SetCslParentUncertainty(aCslParentUncert); 752 } 753 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 754 755 private: 756 static constexpr int8_t kInvalidRssiValue = SubMac::kInvalidRssiValue; 757 static constexpr uint16_t kMaxCcaSampleCount = OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW; 758 759 enum Operation : uint8_t 760 { 761 kOperationIdle = 0, 762 kOperationActiveScan, 763 kOperationEnergyScan, 764 kOperationTransmitBeacon, 765 kOperationTransmitDataDirect, 766 kOperationTransmitPoll, 767 kOperationWaitingForData, 768 #if OPENTHREAD_FTD 769 kOperationTransmitDataIndirect, 770 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 771 kOperationTransmitDataCsl, 772 #endif 773 #endif 774 }; 775 776 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 777 struct RetryHistogram 778 { 779 /** 780 * Histogram of number of retries for a single direct packet until success 781 * [0 retry: packet count, 1 retry: packet count, 2 retry : packet count ... 782 * until max retry limit: packet count] 783 * 784 * The size of the array is OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_DIRECT. 785 */ 786 uint32_t mTxDirectRetrySuccess[OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_DIRECT]; 787 788 /** 789 * Histogram of number of retries for a single indirect packet until success 790 * [0 retry: packet count, 1 retry: packet count, 2 retry : packet count ... 791 * until max retry limit: packet count] 792 * 793 * The size of the array is OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_INDIRECT. 794 */ 795 uint32_t mTxIndirectRetrySuccess[OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_MAX_SIZE_COUNT_INDIRECT]; 796 }; 797 #endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 798 799 Error ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor); 800 void ProcessTransmitSecurity(TxFrame &aFrame); 801 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 802 Error ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame); 803 #endif 804 805 void UpdateIdleMode(void); 806 void StartOperation(Operation aOperation); 807 void FinishOperation(void); 808 void PerformNextOperation(void); 809 TxFrame *PrepareBeaconRequest(void); 810 TxFrame *PrepareBeacon(void); 811 bool ShouldSendBeacon(void) const; 812 bool IsJoinable(void) const; 813 void BeginTransmit(void); 814 bool HandleMacCommand(RxFrame &aFrame); 815 816 static void HandleTimer(Timer &aTimer); 817 void HandleTimer(void); 818 static void HandleOperationTask(Tasklet &aTasklet); 819 820 void Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanDuration); 821 Error UpdateScanChannel(void); 822 void PerformActiveScan(void); 823 void ReportActiveScanResult(const RxFrame *aBeaconFrame); 824 Error ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult); 825 void PerformEnergyScan(void); 826 void ReportEnergyScanResult(int8_t aRssi); 827 Error SignalNetworkNameChange(Error aError); 828 829 void LogFrameRxFailure(const RxFrame *aFrame, Error aError) const; 830 void LogFrameTxFailure(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx) const; 831 void LogBeacon(const char *aActionText, const BeaconPayload &aBeaconPayload) const; 832 833 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 834 uint8_t GetTimeIeOffset(const Frame &aFrame); 835 #endif 836 837 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 838 void ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr); 839 #endif 840 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 841 void ProcessEnhAckProbing(const RxFrame &aFrame, const Neighbor &aNeighbor); 842 #endif 843 static const char *OperationToString(Operation aOperation); 844 845 static const otMacKey sMode2Key; 846 static const otExtAddress sMode2ExtAddress; 847 static const otExtendedPanId sExtendedPanidInit; 848 static const char sNetworkNameInit[]; 849 static const char sDomainNameInit[]; 850 851 bool mEnabled : 1; 852 bool mPendingActiveScan : 1; 853 bool mPendingEnergyScan : 1; 854 bool mPendingTransmitBeacon : 1; 855 bool mPendingTransmitDataDirect : 1; 856 #if OPENTHREAD_FTD 857 bool mPendingTransmitDataIndirect : 1; 858 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 859 bool mPendingTransmitDataCsl : 1; 860 #endif 861 #endif 862 bool mPendingTransmitPoll : 1; 863 bool mPendingWaitingForData : 1; 864 bool mShouldTxPollBeforeData : 1; 865 bool mRxOnWhenIdle : 1; 866 bool mPromiscuous : 1; 867 bool mBeaconsEnabled : 1; 868 bool mUsingTemporaryChannel : 1; 869 #if OPENTHREAD_CONFIG_MAC_STAY_AWAKE_BETWEEN_FRAGMENTS 870 bool mShouldDelaySleep : 1; 871 bool mDelayingSleep : 1; 872 #endif 873 874 Operation mOperation; 875 uint8_t mBeaconSequence; 876 uint8_t mDataSequence; 877 uint8_t mBroadcastTransmitCount; 878 PanId mPanId; 879 uint8_t mPanChannel; 880 uint8_t mRadioChannel; 881 ChannelMask mSupportedChannelMask; 882 ExtendedPanId mExtendedPanId; 883 NetworkName mNetworkName; 884 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) 885 DomainName mDomainName; 886 #endif 887 uint8_t mScanChannel; 888 uint16_t mScanDuration; 889 ChannelMask mScanChannelMask; 890 uint8_t mMaxFrameRetriesDirect; 891 #if OPENTHREAD_FTD 892 uint8_t mMaxFrameRetriesIndirect; 893 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 894 TimeMilli mCslTxFireTime; 895 #endif 896 #endif 897 898 union 899 { 900 ActiveScanHandler mActiveScanHandler; 901 EnergyScanHandler mEnergyScanHandler; 902 }; 903 904 void *mScanHandlerContext; 905 906 Links mLinks; 907 Tasklet mOperationTask; 908 TimerMilli mTimer; 909 otMacCounters mCounters; 910 uint32_t mKeyIdMode2FrameCounter; 911 SuccessRateTracker mCcaSuccessRateTracker; 912 uint16_t mCcaSampleCount; 913 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE 914 RetryHistogram mRetryHistogram; 915 #endif 916 917 #if OPENTHREAD_CONFIG_MULTI_RADIO 918 RadioTypes mTxPendingRadioLinks; 919 RadioTypes mTxBeaconRadioLinks; 920 Error mTxError; 921 #endif 922 923 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE 924 Filter mFilter; 925 #endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE 926 }; 927 928 /** 929 * @} 930 * 931 */ 932 933 } // namespace Mac 934 } // namespace ot 935 936 #endif // MAC_HPP_ 937