• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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