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 forwarding IPv6 datagrams across the Thread mesh. 32 */ 33 34 #ifndef MESH_FORWARDER_HPP_ 35 #define MESH_FORWARDER_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/as_core_type.hpp" 40 #include "common/clearable.hpp" 41 #include "common/frame_data.hpp" 42 #include "common/locator.hpp" 43 #include "common/log.hpp" 44 #include "common/non_copyable.hpp" 45 #include "common/owned_ptr.hpp" 46 #include "common/tasklet.hpp" 47 #include "common/time_ticker.hpp" 48 #include "mac/channel_mask.hpp" 49 #include "mac/data_poll_sender.hpp" 50 #include "mac/mac.hpp" 51 #include "mac/mac_frame.hpp" 52 #include "net/ip6.hpp" 53 #include "thread/address_resolver.hpp" 54 #include "thread/child.hpp" 55 #include "thread/indirect_sender.hpp" 56 #include "thread/lowpan.hpp" 57 #include "thread/network_data_leader.hpp" 58 59 namespace ot { 60 61 namespace Mle { 62 class DiscoverScanner; 63 } 64 65 namespace Utils { 66 class HistoryTracker; 67 } 68 69 /** 70 * @addtogroup core-mesh-forwarding 71 * 72 * @brief 73 * This module includes definitions for mesh forwarding within Thread. 74 * 75 * @{ 76 */ 77 78 /** 79 * Represents link-specific information for messages received from the Thread radio. 80 * 81 */ 82 class ThreadLinkInfo : public otThreadLinkInfo, public Clearable<ThreadLinkInfo> 83 { 84 public: 85 /** 86 * Returns the IEEE 802.15.4 Source PAN ID. 87 * 88 * @returns The IEEE 802.15.4 Source PAN ID. 89 * 90 */ GetPanId(void) const91 Mac::PanId GetPanId(void) const { return mPanId; } 92 93 /** 94 * Returns the IEEE 802.15.4 Channel. 95 * 96 * @returns The IEEE 802.15.4 Channel. 97 * 98 */ GetChannel(void) const99 uint8_t GetChannel(void) const { return mChannel; } 100 101 /** 102 * Returns whether the Destination PAN ID is broadcast. 103 * 104 * @retval TRUE If Destination PAN ID is broadcast. 105 * @retval FALSE If Destination PAN ID is not broadcast. 106 * 107 */ IsDstPanIdBroadcast(void) const108 bool IsDstPanIdBroadcast(void) const { return mIsDstPanIdBroadcast; } 109 110 /** 111 * Indicates whether or not link security is enabled. 112 * 113 * @retval TRUE If link security is enabled. 114 * @retval FALSE If link security is not enabled. 115 * 116 */ IsLinkSecurityEnabled(void) const117 bool IsLinkSecurityEnabled(void) const { return mLinkSecurity; } 118 119 /** 120 * Returns the Received Signal Strength (RSS) in dBm. 121 * 122 * @returns The Received Signal Strength (RSS) in dBm. 123 * 124 */ GetRss(void) const125 int8_t GetRss(void) const { return mRss; } 126 127 /** 128 * Returns the frame/radio Link Quality Indicator (LQI) value. 129 * 130 * @returns The Link Quality Indicator value. 131 * 132 */ GetLqi(void) const133 uint8_t GetLqi(void) const { return mLqi; } 134 135 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 136 /** 137 * Returns the Time Sync Sequence. 138 * 139 * @returns The Time Sync Sequence. 140 * 141 */ GetTimeSyncSeq(void) const142 uint8_t GetTimeSyncSeq(void) const { return mTimeSyncSeq; } 143 144 /** 145 * Returns the time offset to the Thread network time (in microseconds). 146 * 147 * @returns The time offset to the Thread network time (in microseconds). 148 * 149 */ GetNetworkTimeOffset(void) const150 int64_t GetNetworkTimeOffset(void) const { return mNetworkTimeOffset; } 151 #endif 152 153 /** 154 * Sets the `ThreadLinkInfo` from a given received frame. 155 * 156 * @param[in] aFrame A received frame. 157 * 158 */ 159 void SetFrom(const Mac::RxFrame &aFrame); 160 }; 161 162 /** 163 * Implements mesh forwarding within Thread. 164 * 165 */ 166 class MeshForwarder : public InstanceLocator, private NonCopyable 167 { 168 friend class Mac::Mac; 169 friend class Instance; 170 friend class DataPollSender; 171 friend class IndirectSender; 172 friend class Ip6::Ip6; 173 friend class Mle::DiscoverScanner; 174 friend class TimeTicker; 175 176 public: 177 /** 178 * Initializes the object. 179 * 180 * @param[in] aInstance A reference to the OpenThread instance. 181 * 182 */ 183 explicit MeshForwarder(Instance &aInstance); 184 185 /** 186 * Enables mesh forwarding and the IEEE 802.15.4 MAC layer. 187 * 188 */ 189 void Start(void); 190 191 /** 192 * Disables mesh forwarding and the IEEE 802.15.4 MAC layer. 193 * 194 */ 195 void Stop(void); 196 197 /** 198 * Submits a message to the mesh forwarder for forwarding. 199 * 200 * @param[in] aMessagePtr An owned pointer to a message (transfer ownership). 201 * 202 */ 203 void SendMessage(OwnedPtr<Message> aMessagePtr); 204 205 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 206 /** 207 * Sends an empty data frame to the parent. 208 * 209 * @retval kErrorNone Successfully enqueued an empty message. 210 * @retval kErrorInvalidState Device is not in Rx-Off-When-Idle mode or it has no parent. 211 * @retval kErrorNoBufs Insufficient message buffers available. 212 * 213 */ 214 Error SendEmptyMessage(void); 215 #endif 216 217 /** 218 * Is called by the address resolver when an EID-to-RLOC mapping has been resolved. 219 * 220 * @param[in] aEid A reference to the EID that has been resolved. 221 * @param[in] aError kErrorNone on success and kErrorDrop otherwise. 222 * 223 */ 224 void HandleResolved(const Ip6::Address &aEid, Error aError); 225 226 /** 227 * Indicates whether or not rx-on-when-idle mode is enabled. 228 * 229 * @retval TRUE The rx-on-when-idle mode is enabled. 230 * @retval FALSE The rx-on-when-idle-mode is disabled. 231 * 232 */ 233 bool GetRxOnWhenIdle(void) const; 234 235 /** 236 * Sets the rx-on-when-idle mode 237 * 238 * @param[in] aRxOnWhenIdle TRUE to enable, FALSE otherwise. 239 * 240 */ 241 void SetRxOnWhenIdle(bool aRxOnWhenIdle); 242 243 #if OPENTHREAD_FTD 244 245 /** 246 * Represents a predicate function for checking if a given `Message` meets specific criteria. 247 * 248 * @param[in] aMessage The message to evaluate. 249 * 250 * @return TRUE If the @p aMessage satisfies the predicate condition. 251 * @return FALSE If the @p aMessage does not satisfy the predicate condition. 252 * 253 */ 254 typedef bool (&MessageChecker)(const Message &aMessage); 255 256 /** 257 * Removes and frees messages queued for a child, based on a given predicate. 258 * 259 * The `aChild` can be either sleepy or non-sleepy. 260 * 261 * @param[in] aChild The child whose messages are to be evaluated. 262 * @param[in] aMessageChecker The predicate function to filter messages. 263 * 264 */ 265 void RemoveMessagesForChild(Child &aChild, MessageChecker aMessageChecker); 266 267 #endif // OPENTHREAD_FTD 268 269 /** 270 * Frees unicast/multicast MLE Data Responses from Send Message Queue if any. 271 * 272 */ 273 void RemoveDataResponseMessages(void); 274 275 /** 276 * Evicts the message with lowest priority in the send queue. 277 * 278 * @param[in] aPriority The highest priority level of the evicted message. 279 * 280 * @retval kErrorNone Successfully evicted a low priority message. 281 * @retval kErrorNotFound No low priority messages available to evict. 282 * 283 */ 284 Error EvictMessage(Message::Priority aPriority); 285 286 /** 287 * Returns a reference to the send queue. 288 * 289 * @returns A reference to the send queue. 290 * 291 */ GetSendQueue(void) const292 const PriorityQueue &GetSendQueue(void) const { return mSendQueue; } 293 294 /** 295 * Returns a reference to the reassembly queue. 296 * 297 * @returns A reference to the reassembly queue. 298 * 299 */ GetReassemblyQueue(void) const300 const MessageQueue &GetReassemblyQueue(void) const { return mReassemblyList; } 301 302 /** 303 * Returns a reference to the IP level counters. 304 * 305 * @returns A reference to the IP level counters. 306 * 307 */ GetCounters(void) const308 const otIpCounters &GetCounters(void) const { return mIpCounters; } 309 310 /** 311 * Resets the IP level counters. 312 * 313 */ ResetCounters(void)314 void ResetCounters(void) { ClearAllBytes(mIpCounters); } 315 316 #if OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_ENABLE 317 /** 318 * Gets the time-in-queue histogram for messages in the TX queue. 319 * 320 * Histogram of the time-in-queue of messages in the transmit queue is collected. The time-in-queue is tracked for 321 * direct transmissions only and is measured as the duration from when a message is added to the transmit queue 322 * until it is passed to the MAC layer for transmission or dropped. 323 * 324 * The histogram is returned as an array of `uint32_t` values with `aNumBins` entries. The first entry in the array 325 * (at index 0) represents the number of messages with a time-in-queue less than `aBinInterval`. The second entry 326 * represents the number of messages with a time-in-queue greater than or equal to `aBinInterval`, but less than 327 * `2 * aBinInterval`. And so on. The last entry represents the number of messages with time-in-queue greater than 328 * or * equal to `(aNumBins - 1) * aBinInterval`. 329 * 330 * The collected statistics can be reset by calling `ResetTimeInQueueStat()`. The histogram information is 331 * collected since the OpenThread instance was initialized or since the last time statistics collection was reset 332 * by calling the `ResetTimeInQueueStat()`. 333 * 334 * @param[out] aNumBins Reference to return the number of bins in histogram (array length). 335 * @param[out] aBinInterval Reference to return the histogram bin interval length in milliseconds. 336 * 337 * @returns A pointer to an array of @p aNumBins entries representing the collected histogram info. 338 * 339 */ GetTimeInQueueHistogram(uint16_t & aNumBins,uint32_t & aBinInterval) const340 const uint32_t *GetTimeInQueueHistogram(uint16_t &aNumBins, uint32_t &aBinInterval) const 341 { 342 return mTxQueueStats.GetHistogram(aNumBins, aBinInterval); 343 } 344 345 /** 346 * Gets the maximum time-in-queue for messages in the TX queue. 347 * 348 * The time-in-queue is tracked for direct transmissions only and is measured as the duration from when a message 349 * is added to the transmit queue until it is passed to the MAC layer for transmission or dropped. 350 * 351 * The collected statistics can be reset by calling `ResetTimeInQueueStat()`. 352 * 353 * @returns The maximum time-in-queue in milliseconds for all messages in the TX queue (so far). 354 * 355 */ GetMaxTimeInQueue(void) const356 uint32_t GetMaxTimeInQueue(void) const { return mTxQueueStats.GetMaxInterval(); } 357 358 /** 359 * Resets the TX queue time-in-queue statistics. 360 * 361 */ ResetTimeInQueueStat(void)362 void ResetTimeInQueueStat(void) { mTxQueueStats.Clear(); } 363 #endif 364 365 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE 366 /** 367 * Handles a deferred ack. 368 * 369 * Some radio links can use deferred ack logic, where a tx request always report `HandleSentFrame()` quickly. The 370 * link layer would wait for the ack and report it at a later time using this method. 371 * 372 * The link layer is expected to call `HandleDeferredAck()` (with success or failure status) for every tx request 373 * on the radio link. 374 * 375 * @param[in] aNeighbor The neighbor for which the deferred ack status is being reported. 376 * @param[in] aError The deferred ack error status: `kErrorNone` to indicate a deferred ack was received, 377 * `kErrorNoAck` to indicate an ack timeout. 378 * 379 */ 380 void HandleDeferredAck(Neighbor &aNeighbor, Error aError); 381 #endif 382 383 private: 384 static constexpr uint8_t kFailedRouterTransmissions = 4; 385 static constexpr uint8_t kFailedCslDataPollTransmissions = 15; 386 387 static constexpr uint8_t kReassemblyTimeout = OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT; // in seconds. 388 static constexpr uint8_t kMeshHeaderFrameMtu = OT_RADIO_FRAME_MAX_SIZE; // Max MTU with a Mesh Header frame. 389 static constexpr uint8_t kMeshHeaderFrameFcsSize = sizeof(uint16_t); // Frame FCS size for Mesh Header frame. 390 391 // Hops left to use in lowpan mesh header: We use `kMaxRouteCost` as 392 // max hops between routers within Thread mesh. We then add two 393 // for possibility of source or destination being a child 394 // (requiring one hop) and one as additional guard increment. 395 static constexpr uint8_t kMeshHeaderHopsLeft = Mle::kMaxRouteCost + 3; 396 397 static constexpr uint32_t kTxDelayInterval = OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL; // In msec 398 399 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 400 static constexpr uint32_t kTimeInQueueMarkEcn = OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_MARK_ECN_INTERVAL; 401 static constexpr uint32_t kTimeInQueueDropMsg = OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_DROP_MSG_INTERVAL; 402 #endif 403 404 enum MessageAction : uint8_t 405 { 406 kMessageReceive, // Indicates that the message was received. 407 kMessageTransmit, // Indicates that the message was sent. 408 kMessagePrepareIndirect, // Indicates that the message is being prepared for indirect tx. 409 kMessageDrop, // Indicates that the outbound message is dropped (e.g., dst unknown). 410 kMessageReassemblyDrop, // Indicates that the message is being dropped from reassembly list. 411 kMessageEvict, // Indicates that the message was evicted. 412 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 413 kMessageMarkEcn, // Indicates that ECN is marked on an outbound message by delay-aware queue management. 414 kMessageQueueMgmtDrop, // Indicates that an outbound message is dropped by delay-aware queue management. 415 #endif 416 #if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0) 417 kMessageFullQueueDrop, // Indicates message drop due to reaching max allowed frames in direct tx queue. 418 #endif 419 }; 420 421 struct RxInfo : public InstanceLocator 422 { 423 static constexpr uint16_t kInfoStringSize = 70; 424 425 typedef String<kInfoStringSize> InfoString; 426 RxInfoot::MeshForwarder::RxInfo427 explicit RxInfo(Instance &aInstance) 428 : InstanceLocator(aInstance) 429 , mParsedIp6Headers(false) 430 { 431 } 432 GetSrcAddrot::MeshForwarder::RxInfo433 const Mac::Address &GetSrcAddr(void) const { return mMacAddrs.mSource; } GetDstAddrot::MeshForwarder::RxInfo434 const Mac::Address &GetDstAddr(void) const { return mMacAddrs.mDestination; } IsLinkSecurityEnabledot::MeshForwarder::RxInfo435 bool IsLinkSecurityEnabled(void) const { return mLinkInfo.IsLinkSecurityEnabled(); } 436 Error ParseIp6Headers(void); 437 InfoString ToString(void) const; 438 439 FrameData mFrameData; 440 ThreadLinkInfo mLinkInfo; 441 Mac::Addresses mMacAddrs; 442 Ip6::Headers mIp6Headers; 443 bool mParsedIp6Headers; 444 }; 445 446 #if OPENTHREAD_FTD 447 class FragmentPriorityList : public Clearable<FragmentPriorityList> 448 { 449 public: 450 class Entry : public Clearable<Entry> 451 { 452 friend class FragmentPriorityList; 453 454 public: 455 // Lifetime of an entry in seconds. 456 static constexpr uint8_t kLifetime = 457 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 458 OT_MAX(kReassemblyTimeout, OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_RETAIN_TIME); 459 #else 460 kReassemblyTimeout; 461 #endif 462 GetPriority(void) const463 Message::Priority GetPriority(void) const { return static_cast<Message::Priority>(mPriority); } IsExpired(void) const464 bool IsExpired(void) const { return (mLifetime == 0); } DecrementLifetime(void)465 void DecrementLifetime(void) { mLifetime--; } ResetLifetime(void)466 void ResetLifetime(void) { mLifetime = kLifetime; } 467 Matches(uint16_t aSrcRloc16,uint16_t aTag) const468 bool Matches(uint16_t aSrcRloc16, uint16_t aTag) const 469 { 470 return (mSrcRloc16 == aSrcRloc16) && (mDatagramTag == aTag); 471 } 472 473 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE ShouldDrop(void) const474 bool ShouldDrop(void) const { return mShouldDrop; } MarkToDrop(void)475 void MarkToDrop(void) { mShouldDrop = true; } 476 #endif 477 478 private: 479 uint16_t mSrcRloc16; 480 uint16_t mDatagramTag; 481 uint8_t mLifetime; 482 uint8_t mPriority : 2; 483 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 484 bool mShouldDrop : 1; 485 #endif 486 487 static_assert(Message::kNumPriorities <= 4, "mPriority as a 2-bit does not fit all `Priority` values"); 488 }; 489 490 Entry *AllocateEntry(uint16_t aSrcRloc16, uint16_t aTag, Message::Priority aPriority); 491 Entry *FindEntry(uint16_t aSrcRloc16, uint16_t aTag); 492 bool UpdateOnTimeTick(void); 493 494 private: 495 static constexpr uint16_t kNumEntries = 496 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 497 OT_MAX(OPENTHREAD_CONFIG_NUM_FRAGMENT_PRIORITY_ENTRIES, 498 OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_ENTRY_LIST_SIZE); 499 #else 500 OPENTHREAD_CONFIG_NUM_FRAGMENT_PRIORITY_ENTRIES; 501 #endif 502 503 Entry mEntries[kNumEntries]; 504 }; 505 #endif // OPENTHREAD_FTD 506 507 #if OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_ENABLE 508 class TxQueueStats : public Clearable<TxQueueStats> 509 { 510 public: 511 const uint32_t *GetHistogram(uint16_t &aNumBins, uint32_t &aBinInterval) const; GetMaxInterval(void) const512 uint32_t GetMaxInterval(void) const { return mMaxInterval; } 513 void UpdateFor(const Message &aMessage); 514 515 private: 516 static constexpr uint32_t kHistMaxInterval = OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_HISTOGRAM_MAX_INTERVAL; 517 static constexpr uint32_t kHistBinInterval = OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_HISTOGRAM_BIN_INTERVAL; 518 static constexpr uint16_t kNumHistBins = (kHistMaxInterval + kHistBinInterval - 1) / kHistBinInterval; 519 520 uint32_t mMaxInterval; 521 uint32_t mHistogram[kNumHistBins]; 522 }; 523 #endif 524 525 void SendIcmpErrorIfDstUnreach(const Message &aMessage, const Mac::Addresses &aMacAddrs); 526 Error CheckReachability(RxInfo &aRxInfo); 527 Error CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header); 528 void UpdateRoutes(RxInfo &aRxInfo); 529 Error FrameToMessage(RxInfo &aRxInfo, uint16_t aDatagramSize, Message *&aMessage); 530 void GetMacDestinationAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr); 531 void GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr); 532 Message *PrepareNextDirectTransmission(void); 533 void HandleMesh(RxInfo &aRxInfo); 534 void ResolveRoutingLoops(uint16_t aSourceRloc16, uint16_t aDestRloc16); 535 void HandleFragment(RxInfo &aRxInfo); 536 void HandleLowpanHc(RxInfo &aRxInfo); 537 538 void PrepareMacHeaders(Mac::TxFrame &aFrame, 539 Mac::Frame::Type aFrameType, 540 const Mac::Addresses &aMacAddr, 541 const Mac::PanIds &aPanIds, 542 Mac::Frame::SecurityLevel aSecurityLevel, 543 Mac::Frame::KeyIdMode aKeyIdMode, 544 const Message *aMessage); 545 uint16_t PrepareDataFrame(Mac::TxFrame &aFrame, 546 Message &aMessage, 547 const Mac::Addresses &aMacAddrs, 548 bool aAddMeshHeader, 549 uint16_t aMeshSource, 550 uint16_t aMeshDest, 551 bool aAddFragHeader); 552 uint16_t PrepareDataFrameWithNoMeshHeader(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs); 553 void PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &aMacDest, bool aAckRequest); 554 555 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 556 Error UpdateEcnOrDrop(Message &aMessage, bool aPreparingToSend); 557 Error RemoveAgedMessages(void); 558 #endif 559 #if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0) 560 bool IsDirectTxQueueOverMaxFrameThreshold(void) const; 561 void ApplyDirectTxQueueLimit(Message &aMessage); 562 #endif 563 void SendMesh(Message &aMessage, Mac::TxFrame &aFrame); 564 void SendDestinationUnreachable(uint16_t aMeshSource, const Ip6::Headers &aIp6Headers); 565 Error UpdateIp6Route(Message &aMessage); 566 Error UpdateIp6RouteFtd(const Ip6::Header &aIp6Header, Message &aMessage); 567 Error UpdateMeshRoute(Message &aMessage); 568 bool UpdateReassemblyList(void); 569 void UpdateFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader, 570 uint16_t aFragmentLength, 571 uint16_t aSrcRloc16, 572 Message::Priority aPriority); 573 Error HandleDatagram(Message &aMessage, const Mac::Address &aMacSource); 574 void ClearReassemblyList(void); 575 void EvictMessage(Message &aMessage); 576 void HandleDiscoverComplete(void); 577 578 void HandleReceivedFrame(Mac::RxFrame &aFrame); 579 Mac::TxFrame *HandleFrameRequest(Mac::TxFrames &aTxFrames); 580 Neighbor *UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, 581 Error aError, 582 const Mac::Address &aMacDest, 583 bool aIsDataPoll); 584 void UpdateNeighborLinkFailures(Neighbor &aNeighbor, Error aError, bool aAllowNeighborRemove, uint8_t aFailLimit); 585 void HandleSentFrame(Mac::TxFrame &aFrame, Error aError); 586 void UpdateSendMessage(Error aFrameTxError, Mac::Address &aMacDest, Neighbor *aNeighbor); 587 void FinalizeMessageDirectTx(Message &aMessage, Error aError); 588 bool RemoveMessageIfNoPendingTx(Message &aMessage); 589 590 void HandleTimeTick(void); 591 void ScheduleTransmissionTask(void); 592 593 Error GetFramePriority(RxInfo &aRxInfo, Message::Priority &aPriority); 594 Error GetFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader, 595 uint16_t aSrcRloc16, 596 Message::Priority &aPriority); 597 void GetForwardFramePriority(RxInfo &aRxInfo, Message::Priority &aPriority); 598 599 bool CalcIePresent(const Message *aMessage); 600 Mac::Frame::Version CalcFrameVersion(const Neighbor *aNeighbor, bool aIePresent) const; 601 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 602 void AppendHeaderIe(const Message *aMessage, Mac::TxFrame &aFrame); 603 #endif 604 PauseMessageTransmissions(void)605 void PauseMessageTransmissions(void) { mTxPaused = true; } 606 void ResumeMessageTransmissions(void); 607 608 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE 609 void HandleTxDelayTimer(void); 610 #endif 611 612 void LogMessage(MessageAction aAction, const Message &aMessage); 613 void LogMessage(MessageAction aAction, const Message &aMessage, Error aError); 614 void LogMessage(MessageAction aAction, const Message &aMessage, Error aError, const Mac::Address *aAddress); 615 void LogFrame(const char *aActionText, const Mac::Frame &aFrame, Error aError); 616 void LogFragmentFrameDrop(Error aError, const RxInfo &aRxInfo, const Lowpan::FragmentHeader &aFragmentHeader); 617 void LogLowpanHcFrameDrop(Error aError, const RxInfo &aRxInfo); 618 619 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) 620 const char *MessageActionToString(MessageAction aAction, Error aError); 621 const char *MessagePriorityToString(const Message &aMessage); 622 623 #if OPENTHREAD_FTD 624 Error LogMeshFragmentHeader(MessageAction aAction, 625 const Message &aMessage, 626 const Mac::Address *aMacAddress, 627 Error aError, 628 uint16_t &aOffset, 629 Mac::Addresses &aMeshAddrs, 630 LogLevel aLogLevel); 631 void LogMeshIpHeader(const Message &aMessage, 632 uint16_t aOffset, 633 const Mac::Addresses &aMeshAddrs, 634 LogLevel aLogLevel); 635 void LogMeshMessage(MessageAction aAction, 636 const Message &aMessage, 637 const Mac::Address *aAddress, 638 Error aError, 639 LogLevel aLogLevel); 640 #endif 641 void LogIp6SourceDestAddresses(const Ip6::Headers &aHeaders, LogLevel aLogLevel); 642 void LogIp6Message(MessageAction aAction, 643 const Message &aMessage, 644 const Mac::Address *aAddress, 645 Error aError, 646 LogLevel aLogLevel); 647 #endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) 648 649 using TxTask = TaskletIn<MeshForwarder, &MeshForwarder::ScheduleTransmissionTask>; 650 651 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE 652 using TxDelayTimer = TimerMilliIn<MeshForwarder, &MeshForwarder::HandleTxDelayTimer>; 653 #endif 654 655 PriorityQueue mSendQueue; 656 MessageQueue mReassemblyList; 657 uint16_t mFragTag; 658 uint16_t mMessageNextOffset; 659 660 Message *mSendMessage; 661 662 Mac::Addresses mMacAddrs; 663 uint16_t mMeshSource; 664 uint16_t mMeshDest; 665 bool mAddMeshHeader : 1; 666 bool mEnabled : 1; 667 bool mTxPaused : 1; 668 bool mSendBusy : 1; 669 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE 670 bool mDelayNextTx : 1; 671 TxDelayTimer mTxDelayTimer; 672 #endif 673 674 TxTask mScheduleTransmissionTask; 675 676 otIpCounters mIpCounters; 677 678 #if OPENTHREAD_FTD 679 FragmentPriorityList mFragmentPriorityList; 680 IndirectSender mIndirectSender; 681 #endif 682 683 DataPollSender mDataPollSender; 684 685 #if OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_ENABLE 686 TxQueueStats mTxQueueStats; 687 #endif 688 }; 689 690 /** 691 * @} 692 * 693 */ 694 695 DefineCoreType(otThreadLinkInfo, ThreadLinkInfo); 696 697 } // namespace ot 698 699 #endif // MESH_FORWARDER_HPP_ 700