xref: /aosp_15_r20/external/openthread/src/core/thread/mesh_forwarder.hpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
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