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