• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2019, 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 handling indirect transmission.
32  */
33 
34 #ifndef INDIRECT_SENDER_HPP_
35 #define INDIRECT_SENDER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/locator.hpp"
40 #include "common/message.hpp"
41 #include "common/non_copyable.hpp"
42 #include "mac/data_poll_handler.hpp"
43 #include "mac/mac_frame.hpp"
44 #include "thread/csl_tx_scheduler.hpp"
45 #include "thread/indirect_sender_frame_context.hpp"
46 #include "thread/mle_types.hpp"
47 #include "thread/src_match_controller.hpp"
48 
49 namespace ot {
50 
51 /**
52  * @addtogroup core-mesh-forwarding
53  *
54  * @brief
55  *   This module includes definitions for handling indirect transmissions.
56  *
57  * @{
58  */
59 
60 #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
61 
62 class CslNeighbor;
63 #if OPENTHREAD_FTD
64 class Child;
65 #endif
66 
67 /**
68  * Implements indirect transmission.
69  */
70 class IndirectSender : public InstanceLocator, public IndirectSenderBase, private NonCopyable
71 {
72     friend class Instance;
73 #if OPENTHREAD_FTD
74     friend class DataPollHandler;
75 #endif
76 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
77     friend class CslTxScheduler;
78 #endif
79 
80 public:
81     /**
82      * Defines all the neighbor info required for indirect (CSL or data-poll) transmission.
83      *
84      * Sub-classes of `Neighbor`, e.g., `CslNeighbor` or `Child` publicly inherits from this class.
85      */
86     class NeighborInfo
87     {
88         friend class IndirectSender;
89 #if OPENTHREAD_FTD
90         friend class DataPollHandler;
91         friend class SourceMatchController;
92 #endif
93         friend class CslTxScheduler;
94 
95     public:
96         /**
97          * Returns the number of queued messages for the child.
98          *
99          * @returns Number of queued messages for the child.
100          */
GetIndirectMessageCount(void) const101         uint16_t GetIndirectMessageCount(void) const { return mQueuedMessageCount; }
102 
103     private:
GetIndirectMessage(void)104         Message *GetIndirectMessage(void) { return mIndirectMessage; }
SetIndirectMessage(Message * aMessage)105         void     SetIndirectMessage(Message *aMessage) { mIndirectMessage = aMessage; }
106 
GetIndirectFragmentOffset(void) const107         uint16_t GetIndirectFragmentOffset(void) const { return mIndirectFragmentOffset; }
SetIndirectFragmentOffset(uint16_t aFragmentOffset)108         void     SetIndirectFragmentOffset(uint16_t aFragmentOffset) { mIndirectFragmentOffset = aFragmentOffset; }
109 
GetIndirectTxSuccess(void) const110         bool GetIndirectTxSuccess(void) const { return mIndirectTxSuccess; }
SetIndirectTxSuccess(bool aTxStatus)111         void SetIndirectTxSuccess(bool aTxStatus) { mIndirectTxSuccess = aTxStatus; }
112 
IsIndirectSourceMatchShort(void) const113         bool IsIndirectSourceMatchShort(void) const { return mUseShortAddress; }
SetIndirectSourceMatchShort(bool aShort)114         void SetIndirectSourceMatchShort(bool aShort) { mUseShortAddress = aShort; }
115 
IsIndirectSourceMatchPending(void) const116         bool IsIndirectSourceMatchPending(void) const { return mSourceMatchPending; }
SetIndirectSourceMatchPending(bool aPending)117         void SetIndirectSourceMatchPending(bool aPending) { mSourceMatchPending = aPending; }
118 
IncrementIndirectMessageCount(void)119         void IncrementIndirectMessageCount(void) { mQueuedMessageCount++; }
DecrementIndirectMessageCount(void)120         void DecrementIndirectMessageCount(void) { mQueuedMessageCount--; }
ResetIndirectMessageCount(void)121         void ResetIndirectMessageCount(void) { mQueuedMessageCount = 0; }
122 
IsWaitingForMessageUpdate(void) const123         bool IsWaitingForMessageUpdate(void) const { return mWaitingForMessageUpdate; }
SetWaitingForMessageUpdate(bool aNeedsUpdate)124         void SetWaitingForMessageUpdate(bool aNeedsUpdate) { mWaitingForMessageUpdate = aNeedsUpdate; }
125 
126         const Mac::Address &GetMacAddress(Mac::Address &aMacAddress) const;
127 
128         Message *mIndirectMessage;             // Current indirect message.
129         uint16_t mIndirectFragmentOffset : 14; // 6LoWPAN fragment offset for the indirect message.
130         bool     mIndirectTxSuccess : 1;       // Indicates tx success/failure of current indirect message.
131         bool     mWaitingForMessageUpdate : 1; // Indicates waiting for updating the indirect message.
132         uint16_t mQueuedMessageCount : 14;     // Number of queued indirect messages for the child.
133         bool     mUseShortAddress : 1;         // Indicates whether to use short or extended address.
134         bool     mSourceMatchPending : 1;      // Indicates whether or not pending to add to src match table.
135 
136         static_assert(OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS < (1UL << 14),
137                       "mQueuedMessageCount cannot fit max required!");
138     };
139 
140     /**
141      * Represents a predicate function for checking if a given `Message` meets specific criteria.
142      *
143      * @param[in] aMessage The message to evaluate.
144      *
145      * @retval TRUE   If the @p aMessage satisfies the predicate condition.
146      * @retval FALSE  If the @p aMessage does not satisfy the predicate condition.
147      */
148     typedef bool (&MessageChecker)(const Message &aMessage);
149 
150     /**
151      * Initializes the object.
152      *
153      * @param[in]  aInstance  A reference to the OpenThread instance.
154      */
155     explicit IndirectSender(Instance &aInstance);
156 
157     /**
158      * Enables indirect transmissions.
159      */
Start(void)160     void Start(void) { mEnabled = true; }
161 
162     /**
163      * Disables indirect transmission.
164      *
165      * Any previously scheduled indirect transmission is canceled.
166      */
167     void Stop(void);
168 
169 #if OPENTHREAD_FTD
170     /**
171      * Adds a message for indirect transmission to a sleepy child.
172      *
173      * @param[in] aMessage  The message to add.
174      * @param[in] aChild    The (sleepy) child for indirect transmission.
175      */
176     void AddMessageForSleepyChild(Message &aMessage, Child &aChild);
177 
178     /**
179      * Removes a message for indirect transmission to a sleepy child.
180      *
181      * @param[in] aMessage  The message to update.
182      * @param[in] aChild    The (sleepy) child for indirect transmission.
183      *
184      * @retval kErrorNone          Successfully removed the message for indirect transmission.
185      * @retval kErrorNotFound      The message was not scheduled for indirect transmission to the child.
186      */
187     Error RemoveMessageFromSleepyChild(Message &aMessage, Child &aChild);
188 
189     /**
190      * Removes all added messages for a specific child and frees message (with no indirect/direct tx).
191      *
192      * @param[in]  aChild  A reference to a child whose messages shall be removed.
193      */
194     void ClearAllMessagesForSleepyChild(Child &aChild);
195 
196     /**
197      * Finds the first queued message for a given sleepy child that also satisfies the conditions of a given
198      * `MessageChecker`.
199      *
200      * The caller MUST ensure that @p aChild is sleepy.
201      *
202      * @param[in] aChild     The sleepy child to check.
203      * @param[in] aChecker   The predicate function to apply.
204      *
205      * @returns A pointer to the matching queued message, or `nullptr` if none is found.
206      */
FindQueuedMessageForSleepyChild(const Child & aChild,MessageChecker aChecker)207     Message *FindQueuedMessageForSleepyChild(const Child &aChild, MessageChecker aChecker)
208     {
209         return AsNonConst(AsConst(this)->FindQueuedMessageForSleepyChild(aChild, aChecker));
210     }
211 
212     /**
213      * Finds the first queued message for a given sleepy child that also satisfies the conditions of a given
214      * `MessageChecker`.
215      *
216      * The caller MUST ensure that @p aChild is sleepy.
217      *
218      * @param[in] aChild     The sleepy child to check.
219      * @param[in] aChecker   The predicate function to apply.
220      *
221      * @returns A pointer to the matching queued message, or `nullptr` if none is found.
222      */
223     const Message *FindQueuedMessageForSleepyChild(const Child &aChild, MessageChecker aChecker) const;
224 
225     /**
226      * Indicates whether there is any queued message for a given sleepy child that also satisfies the conditions of a
227      * given `MessageChecker`.
228      *
229      * The caller MUST ensure that @p aChild is sleepy.
230      *
231      * @param[in] aChild    The sleepy child to check for.
232      * @param[in] aChecker  The predicate function to apply.
233      *
234      * @retval TRUE   There is a queued message satisfying @p aChecker for sleepy child @p aChild.
235      * @retval FALSE  There is no queued message satisfying @p aChecker for sleepy child @p aChild.
236      */
HasQueuedMessageForSleepyChild(const Child & aChild,MessageChecker aChecker) const237     bool HasQueuedMessageForSleepyChild(const Child &aChild, MessageChecker aChecker) const
238     {
239         return (FindQueuedMessageForSleepyChild(aChild, aChecker) != nullptr);
240     }
241 
242     /**
243      * Sets whether to use the extended or short address for a child.
244      *
245      * @param[in] aChild            A reference to the child.
246      * @param[in] aUseShortAddress  `true` to use short address, `false` to use extended address.
247      */
248     void SetChildUseShortAddress(Child &aChild, bool aUseShortAddress);
249 
250     /**
251      * Handles a child mode change and updates any queued messages for the child accordingly.
252      *
253      * @param[in]  aChild    The child whose device mode was changed.
254      * @param[in]  aOldMode  The old device mode of the child.
255      */
256     void HandleChildModeChange(Child &aChild, Mle::DeviceMode aOldMode);
257 
258 #endif // OPENTHREAD_FTD
259 
260 private:
261 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
262     // Callbacks from `CslTxScheduler`
263     Error PrepareFrameForCslNeighbor(Mac::TxFrame &aFrame, FrameContext &aContext, CslNeighbor &aCslNeighbor);
264     void  HandleSentFrameToCslNeighbor(const Mac::TxFrame &aFrame,
265                                        const FrameContext &aContext,
266                                        Error               aError,
267                                        CslNeighbor        &aCslNeighbor);
268 #endif
269 
270 #if OPENTHREAD_FTD
271     // Callbacks from `DataPollHandler`
272     Error PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild);
273     void  HandleSentFrameToChild(const Mac::TxFrame &aFrame, const FrameContext &aContext, Error aError, Child &aChild);
274     void  HandleFrameChangeDone(Child &aChild);
275 
276     void     UpdateIndirectMessage(Child &aChild);
277     void     RequestMessageUpdate(Child &aChild);
278     uint16_t PrepareDataFrame(Mac::TxFrame &aFrame, Child &aChild, Message &aMessage);
279     void     PrepareEmptyFrame(Mac::TxFrame &aFrame, Child &aChild, bool aAckRequest);
280     void     ClearMessagesForRemovedChildren(void);
281 
282     static bool AcceptAnyMessage(const Message &aMessage);
283     static bool AcceptSupervisionMessage(const Message &aMessage);
284 #endif // OPENTHREAD_FTD
285 
286     bool mEnabled;
287 #if OPENTHREAD_FTD
288     SourceMatchController mSourceMatchController;
289     DataPollHandler       mDataPollHandler;
290 #endif
291 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
292     CslTxScheduler mCslTxScheduler;
293 #endif
294 };
295 
296 #endif // #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
297 
298 /**
299  * @}
300  */
301 
302 } // namespace ot
303 
304 #endif // INDIRECT_SENDER_HPP_
305