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