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 /** 244 * Sets the scan parameters for MLE Discovery Request messages. 245 * 246 * @param[in] aScanChannels A reference to channel mask indicating which channels to scan. 247 * If @p aScanChannels is empty, then all channels are used instead. 248 * 249 */ 250 void SetDiscoverParameters(const Mac::ChannelMask &aScanChannels); 251 252 #if OPENTHREAD_FTD 253 /** 254 * Frees any messages queued for an existing child. 255 * 256 * @param[in] aChild A reference to the child. 257 * @param[in] aSubType The message sub-type to remove. 258 * Use Message::kSubTypeNone remove all messages for @p aChild. 259 * 260 */ 261 void RemoveMessages(Child &aChild, Message::SubType aSubType); 262 #endif 263 264 /** 265 * Frees unicast/multicast MLE Data Responses from Send Message Queue if any. 266 * 267 */ 268 void RemoveDataResponseMessages(void); 269 270 /** 271 * Evicts the message with lowest priority in the send queue. 272 * 273 * @param[in] aPriority The highest priority level of the evicted message. 274 * 275 * @retval kErrorNone Successfully evicted a low priority message. 276 * @retval kErrorNotFound No low priority messages available to evict. 277 * 278 */ 279 Error EvictMessage(Message::Priority aPriority); 280 281 /** 282 * Returns a reference to the send queue. 283 * 284 * @returns A reference to the send queue. 285 * 286 */ GetSendQueue(void) const287 const PriorityQueue &GetSendQueue(void) const { return mSendQueue; } 288 289 /** 290 * Returns a reference to the reassembly queue. 291 * 292 * @returns A reference to the reassembly queue. 293 * 294 */ GetReassemblyQueue(void) const295 const MessageQueue &GetReassemblyQueue(void) const { return mReassemblyList; } 296 297 /** 298 * Returns a reference to the IP level counters. 299 * 300 * @returns A reference to the IP level counters. 301 * 302 */ GetCounters(void) const303 const otIpCounters &GetCounters(void) const { return mIpCounters; } 304 305 /** 306 * Resets the IP level counters. 307 * 308 */ ResetCounters(void)309 void ResetCounters(void) { ClearAllBytes(mIpCounters); } 310 311 #if OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_ENABLE 312 /** 313 * Gets the time-in-queue histogram for messages in the TX queue. 314 * 315 * Histogram of the time-in-queue of messages in the transmit queue is collected. The time-in-queue is tracked for 316 * direct transmissions only and is measured as the duration from when a message is added to the transmit queue 317 * until it is passed to the MAC layer for transmission or dropped. 318 * 319 * The histogram is returned as an array of `uint32_t` values with `aNumBins` entries. The first entry in the array 320 * (at index 0) represents the number of messages with a time-in-queue less than `aBinInterval`. The second entry 321 * represents the number of messages with a time-in-queue greater than or equal to `aBinInterval`, but less than 322 * `2 * aBinInterval`. And so on. The last entry represents the number of messages with time-in-queue greater than 323 * or * equal to `(aNumBins - 1) * aBinInterval`. 324 * 325 * The collected statistics can be reset by calling `ResetTimeInQueueStat()`. The histogram information is 326 * collected since the OpenThread instance was initialized or since the last time statistics collection was reset 327 * by calling the `ResetTimeInQueueStat()`. 328 * 329 * @param[out] aNumBins Reference to return the number of bins in histogram (array length). 330 * @param[out] aBinInterval Reference to return the histogram bin interval length in milliseconds. 331 * 332 * @returns A pointer to an array of @p aNumBins entries representing the collected histogram info. 333 * 334 */ GetTimeInQueueHistogram(uint16_t & aNumBins,uint32_t & aBinInterval) const335 const uint32_t *GetTimeInQueueHistogram(uint16_t &aNumBins, uint32_t &aBinInterval) const 336 { 337 return mTxQueueStats.GetHistogram(aNumBins, aBinInterval); 338 } 339 340 /** 341 * Gets the maximum time-in-queue for messages in the TX queue. 342 * 343 * The time-in-queue is tracked for direct transmissions only and is measured as the duration from when a message 344 * is added to the transmit queue until it is passed to the MAC layer for transmission or dropped. 345 * 346 * The collected statistics can be reset by calling `ResetTimeInQueueStat()`. 347 * 348 * @returns The maximum time-in-queue in milliseconds for all messages in the TX queue (so far). 349 * 350 */ GetMaxTimeInQueue(void) const351 uint32_t GetMaxTimeInQueue(void) const { return mTxQueueStats.GetMaxInterval(); } 352 353 /** 354 * Resets the TX queue time-in-queue statistics. 355 * 356 */ ResetTimeInQueueStat(void)357 void ResetTimeInQueueStat(void) { mTxQueueStats.Clear(); } 358 #endif 359 360 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE 361 /** 362 * Handles a deferred ack. 363 * 364 * Some radio links can use deferred ack logic, where a tx request always report `HandleSentFrame()` quickly. The 365 * link layer would wait for the ack and report it at a later time using this method. 366 * 367 * The link layer is expected to call `HandleDeferredAck()` (with success or failure status) for every tx request 368 * on the radio link. 369 * 370 * @param[in] aNeighbor The neighbor for which the deferred ack status is being reported. 371 * @param[in] aError The deferred ack error status: `kErrorNone` to indicate a deferred ack was received, 372 * `kErrorNoAck` to indicate an ack timeout. 373 * 374 */ 375 void HandleDeferredAck(Neighbor &aNeighbor, Error aError); 376 #endif 377 378 private: 379 static constexpr uint8_t kFailedRouterTransmissions = 4; 380 static constexpr uint8_t kFailedCslDataPollTransmissions = 15; 381 382 static constexpr uint8_t kReassemblyTimeout = OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT; // in seconds. 383 static constexpr uint8_t kMeshHeaderFrameMtu = OT_RADIO_FRAME_MAX_SIZE; // Max MTU with a Mesh Header frame. 384 static constexpr uint8_t kMeshHeaderFrameFcsSize = sizeof(uint16_t); // Frame FCS size for Mesh Header frame. 385 386 // Hops left to use in lowpan mesh header: We use `kMaxRouteCost` as 387 // max hops between routers within Thread mesh. We then add two 388 // for possibility of source or destination being a child 389 // (requiring one hop) and one as additional guard increment. 390 static constexpr uint8_t kMeshHeaderHopsLeft = Mle::kMaxRouteCost + 3; 391 392 static constexpr uint32_t kTxDelayInterval = OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL; // In msec 393 394 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 395 static constexpr uint32_t kTimeInQueueMarkEcn = OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_MARK_ECN_INTERVAL; 396 static constexpr uint32_t kTimeInQueueDropMsg = OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_DROP_MSG_INTERVAL; 397 #endif 398 399 enum MessageAction : uint8_t 400 { 401 kMessageReceive, // Indicates that the message was received. 402 kMessageTransmit, // Indicates that the message was sent. 403 kMessagePrepareIndirect, // Indicates that the message is being prepared for indirect tx. 404 kMessageDrop, // Indicates that the outbound message is dropped (e.g., dst unknown). 405 kMessageReassemblyDrop, // Indicates that the message is being dropped from reassembly list. 406 kMessageEvict, // Indicates that the message was evicted. 407 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 408 kMessageMarkEcn, // Indicates that ECN is marked on an outbound message by delay-aware queue management. 409 kMessageQueueMgmtDrop, // Indicates that an outbound message is dropped by delay-aware queue management. 410 #endif 411 #if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0) 412 kMessageFullQueueDrop, // Indicates message drop due to reaching max allowed frames in direct tx queue. 413 #endif 414 }; 415 416 enum AnycastType : uint8_t 417 { 418 kAnycastDhcp6Agent, 419 kAnycastNeighborDiscoveryAgent, 420 kAnycastService, 421 }; 422 423 #if OPENTHREAD_FTD 424 class FragmentPriorityList : public Clearable<FragmentPriorityList> 425 { 426 public: 427 class Entry : public Clearable<Entry> 428 { 429 friend class FragmentPriorityList; 430 431 public: 432 // Lifetime of an entry in seconds. 433 static constexpr uint8_t kLifetime = 434 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 435 OT_MAX(kReassemblyTimeout, OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_RETAIN_TIME); 436 #else 437 kReassemblyTimeout; 438 #endif 439 GetPriority(void) const440 Message::Priority GetPriority(void) const { return static_cast<Message::Priority>(mPriority); } IsExpired(void) const441 bool IsExpired(void) const { return (mLifetime == 0); } DecrementLifetime(void)442 void DecrementLifetime(void) { mLifetime--; } ResetLifetime(void)443 void ResetLifetime(void) { mLifetime = kLifetime; } 444 Matches(uint16_t aSrcRloc16,uint16_t aTag) const445 bool Matches(uint16_t aSrcRloc16, uint16_t aTag) const 446 { 447 return (mSrcRloc16 == aSrcRloc16) && (mDatagramTag == aTag); 448 } 449 450 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE ShouldDrop(void) const451 bool ShouldDrop(void) const { return mShouldDrop; } MarkToDrop(void)452 void MarkToDrop(void) { mShouldDrop = true; } 453 #endif 454 455 private: 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 Entry *AllocateEntry(uint16_t aSrcRloc16, uint16_t aTag, Message::Priority aPriority); 468 Entry *FindEntry(uint16_t aSrcRloc16, uint16_t aTag); 469 bool UpdateOnTimeTick(void); 470 471 private: 472 static constexpr uint16_t kNumEntries = 473 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 474 OT_MAX(OPENTHREAD_CONFIG_NUM_FRAGMENT_PRIORITY_ENTRIES, 475 OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_ENTRY_LIST_SIZE); 476 #else 477 OPENTHREAD_CONFIG_NUM_FRAGMENT_PRIORITY_ENTRIES; 478 #endif 479 480 Entry mEntries[kNumEntries]; 481 }; 482 #endif // OPENTHREAD_FTD 483 484 #if OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_ENABLE 485 class TxQueueStats : public Clearable<TxQueueStats> 486 { 487 public: 488 const uint32_t *GetHistogram(uint16_t &aNumBins, uint32_t &aBinInterval) const; GetMaxInterval(void) const489 uint32_t GetMaxInterval(void) const { return mMaxInterval; } 490 void UpdateFor(const Message &aMessage); 491 492 private: 493 static constexpr uint32_t kHistMaxInterval = OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_HISTOGRAM_MAX_INTERVAL; 494 static constexpr uint32_t kHistBinInterval = OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_HISTOGRAM_BIN_INTERVAL; 495 static constexpr uint16_t kNumHistBins = (kHistMaxInterval + kHistBinInterval - 1) / kHistBinInterval; 496 497 uint32_t mMaxInterval; 498 uint32_t mHistogram[kNumHistBins]; 499 }; 500 #endif 501 502 void SendIcmpErrorIfDstUnreach(const Message &aMessage, const Mac::Addresses &aMacAddrs); 503 Error CheckReachability(const FrameData &aFrameData, const Mac::Addresses &aMeshAddrs); 504 void UpdateRoutes(const FrameData &aFrameData, const Mac::Addresses &aMeshAddrs); 505 Error FrameToMessage(const FrameData &aFrameData, 506 uint16_t aDatagramSize, 507 const Mac::Addresses &aMacAddrs, 508 Message *&aMessage); 509 void GetMacDestinationAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr); 510 void GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr); 511 Message *PrepareNextDirectTransmission(void); 512 void HandleMesh(FrameData &aFrameData, const Mac::Address &aMacSource, const ThreadLinkInfo &aLinkInfo); 513 void HandleFragment(FrameData &aFrameData, const Mac::Addresses &aMacAddrs, const ThreadLinkInfo &aLinkInfo); 514 void HandleLowpanHC(const FrameData &aFrameData, const Mac::Addresses &aMacAddrs, const ThreadLinkInfo &aLinkInfo); 515 516 void PrepareMacHeaders(Mac::TxFrame &aFrame, 517 Mac::Frame::Type aFrameType, 518 const Mac::Addresses &aMacAddr, 519 const Mac::PanIds &aPanIds, 520 Mac::Frame::SecurityLevel aSecurityLevel, 521 Mac::Frame::KeyIdMode aKeyIdMode, 522 const Message *aMessage); 523 uint16_t PrepareDataFrame(Mac::TxFrame &aFrame, 524 Message &aMessage, 525 const Mac::Addresses &aMacAddrs, 526 bool aAddMeshHeader, 527 uint16_t aMeshSource, 528 uint16_t aMeshDest, 529 bool aAddFragHeader); 530 uint16_t PrepareDataFrameWithNoMeshHeader(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs); 531 void PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &aMacDest, bool aAckRequest); 532 533 #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 534 Error UpdateEcnOrDrop(Message &aMessage, bool aPreparingToSend); 535 Error RemoveAgedMessages(void); 536 #endif 537 #if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0) 538 bool IsDirectTxQueueOverMaxFrameThreshold(void) const; 539 void ApplyDirectTxQueueLimit(Message &aMessage); 540 #endif 541 void SendMesh(Message &aMessage, Mac::TxFrame &aFrame); 542 void SendDestinationUnreachable(uint16_t aMeshSource, const Ip6::Headers &aIp6Headers); 543 Error UpdateIp6Route(Message &aMessage); 544 Error UpdateIp6RouteFtd(const Ip6::Header &aIp6Header, Message &aMessage); 545 void EvaluateRoutingCost(uint16_t aDest, uint8_t &aBestCost, uint16_t &aBestDest) const; 546 Error AnycastRouteLookup(uint8_t aServiceId, AnycastType aType, uint16_t &aMeshDest) const; 547 Error UpdateMeshRoute(Message &aMessage); 548 bool UpdateReassemblyList(void); 549 void UpdateFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader, 550 uint16_t aFragmentLength, 551 uint16_t aSrcRloc16, 552 Message::Priority aPriority); 553 Error HandleDatagram(Message &aMessage, const Mac::Address &aMacSource); 554 void ClearReassemblyList(void); 555 void EvictMessage(Message &aMessage); 556 void HandleDiscoverComplete(void); 557 558 void HandleReceivedFrame(Mac::RxFrame &aFrame); 559 Mac::TxFrame *HandleFrameRequest(Mac::TxFrames &aTxFrames); 560 Neighbor *UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, 561 Error aError, 562 const Mac::Address &aMacDest, 563 bool aIsDataPoll); 564 void UpdateNeighborLinkFailures(Neighbor &aNeighbor, Error aError, bool aAllowNeighborRemove, uint8_t aFailLimit); 565 void HandleSentFrame(Mac::TxFrame &aFrame, Error aError); 566 void UpdateSendMessage(Error aFrameTxError, Mac::Address &aMacDest, Neighbor *aNeighbor); 567 void FinalizeMessageDirectTx(Message &aMessage, Error aError); 568 bool RemoveMessageIfNoPendingTx(Message &aMessage); 569 570 void HandleTimeTick(void); 571 void ScheduleTransmissionTask(void); 572 573 Error GetFramePriority(const FrameData &aFrameData, const Mac::Addresses &aMacAddrs, Message::Priority &aPriority); 574 Error GetFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader, 575 uint16_t aSrcRloc16, 576 Message::Priority &aPriority); 577 void GetForwardFramePriority(const FrameData &aFrameData, 578 const Mac::Addresses &aMeshAddrs, 579 Message::Priority &aPriority); 580 581 bool CalcIePresent(const Message *aMessage); 582 Mac::Frame::Version CalcFrameVersion(const Neighbor *aNeighbor, bool aIePresent) const; 583 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 584 void AppendHeaderIe(const Message *aMessage, Mac::TxFrame &aFrame); 585 #endif 586 PauseMessageTransmissions(void)587 void PauseMessageTransmissions(void) { mTxPaused = true; } 588 void ResumeMessageTransmissions(void); 589 590 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE 591 void HandleTxDelayTimer(void); 592 #endif 593 594 void LogMessage(MessageAction aAction, const Message &aMessage); 595 void LogMessage(MessageAction aAction, const Message &aMessage, Error aError); 596 void LogMessage(MessageAction aAction, const Message &aMessage, Error aError, const Mac::Address *aAddress); 597 void LogFrame(const char *aActionText, const Mac::Frame &aFrame, Error aError); 598 void LogFragmentFrameDrop(Error aError, 599 uint16_t aFrameLength, 600 const Mac::Addresses &aMacAddrs, 601 const Lowpan::FragmentHeader &aFragmentHeader, 602 bool aIsSecure); 603 void LogLowpanHcFrameDrop(Error aError, uint16_t aFrameLength, const Mac::Addresses &aMacAddrs, bool aIsSecure); 604 605 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) 606 const char *MessageActionToString(MessageAction aAction, Error aError); 607 const char *MessagePriorityToString(const Message &aMessage); 608 609 #if OPENTHREAD_FTD 610 Error LogMeshFragmentHeader(MessageAction aAction, 611 const Message &aMessage, 612 const Mac::Address *aMacAddress, 613 Error aError, 614 uint16_t &aOffset, 615 Mac::Addresses &aMeshAddrs, 616 LogLevel aLogLevel); 617 void LogMeshIpHeader(const Message &aMessage, 618 uint16_t aOffset, 619 const Mac::Addresses &aMeshAddrs, 620 LogLevel aLogLevel); 621 void LogMeshMessage(MessageAction aAction, 622 const Message &aMessage, 623 const Mac::Address *aAddress, 624 Error aError, 625 LogLevel aLogLevel); 626 #endif 627 void LogIp6SourceDestAddresses(const Ip6::Headers &aHeaders, LogLevel aLogLevel); 628 void LogIp6Message(MessageAction aAction, 629 const Message &aMessage, 630 const Mac::Address *aAddress, 631 Error aError, 632 LogLevel aLogLevel); 633 #endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) 634 635 using TxTask = TaskletIn<MeshForwarder, &MeshForwarder::ScheduleTransmissionTask>; 636 637 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE 638 using TxDelayTimer = TimerMilliIn<MeshForwarder, &MeshForwarder::HandleTxDelayTimer>; 639 #endif 640 641 PriorityQueue mSendQueue; 642 MessageQueue mReassemblyList; 643 uint16_t mFragTag; 644 uint16_t mMessageNextOffset; 645 646 Message *mSendMessage; 647 648 Mac::Addresses mMacAddrs; 649 uint16_t mMeshSource; 650 uint16_t mMeshDest; 651 bool mAddMeshHeader : 1; 652 bool mEnabled : 1; 653 bool mTxPaused : 1; 654 bool mSendBusy : 1; 655 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE 656 bool mDelayNextTx : 1; 657 TxDelayTimer mTxDelayTimer; 658 #endif 659 660 TxTask mScheduleTransmissionTask; 661 662 otIpCounters mIpCounters; 663 664 #if OPENTHREAD_FTD 665 FragmentPriorityList mFragmentPriorityList; 666 IndirectSender mIndirectSender; 667 #endif 668 669 DataPollSender mDataPollSender; 670 671 #if OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_ENABLE 672 TxQueueStats mTxQueueStats; 673 #endif 674 }; 675 676 /** 677 * @} 678 * 679 */ 680 681 DefineCoreType(otThreadLinkInfo, ThreadLinkInfo); 682 683 } // namespace ot 684 685 #endif // MESH_FORWARDER_HPP_ 686