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 #if OPENTHREAD_FTD
40 
41 #include "common/locator.hpp"
42 #include "common/message.hpp"
43 #include "common/non_copyable.hpp"
44 #include "mac/data_poll_handler.hpp"
45 #include "mac/mac_frame.hpp"
46 #include "thread/csl_tx_scheduler.hpp"
47 #include "thread/indirect_sender_frame_context.hpp"
48 #include "thread/mle_types.hpp"
49 #include "thread/src_match_controller.hpp"
50 
51 namespace ot {
52 
53 /**
54  * @addtogroup core-mesh-forwarding
55  *
56  * @brief
57  *   This module includes definitions for handling indirect transmissions.
58  *
59  * @{
60  */
61 
62 class Child;
63 
64 /**
65  * This class implements indirect transmission.
66  *
67  */
68 class IndirectSender : public InstanceLocator, public IndirectSenderBase, private NonCopyable
69 {
70     friend class Instance;
71     friend class DataPollHandler::Callbacks;
72 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
73     friend class CslTxScheduler::Callbacks;
74 #endif
75 
76 public:
77     /**
78      * This class defines all the child info required for indirect transmission.
79      *
80      * `Child` class publicly inherits from this class.
81      *
82      */
83     class ChildInfo
84     {
85         friend class IndirectSender;
86         friend class DataPollHandler;
87         friend class CslTxScheduler;
88         friend class SourceMatchController;
89 
90     public:
91         /**
92          * This method returns the number of queued messages for the child.
93          *
94          * @returns Number of queued messages for the child.
95          *
96          */
GetIndirectMessageCount(void) const97         uint16_t GetIndirectMessageCount(void) const { return mQueuedMessageCount; }
98 
99     private:
GetIndirectMessage(void)100         Message *GetIndirectMessage(void) { return mIndirectMessage; }
SetIndirectMessage(Message * aMessage)101         void     SetIndirectMessage(Message *aMessage) { mIndirectMessage = aMessage; }
102 
GetIndirectFragmentOffset(void) const103         uint16_t GetIndirectFragmentOffset(void) const { return mIndirectFragmentOffset; }
SetIndirectFragmentOffset(uint16_t aFragmentOffset)104         void     SetIndirectFragmentOffset(uint16_t aFragmentOffset) { mIndirectFragmentOffset = aFragmentOffset; }
105 
GetIndirectTxSuccess(void) const106         bool GetIndirectTxSuccess(void) const { return mIndirectTxSuccess; }
SetIndirectTxSuccess(bool aTxStatus)107         void SetIndirectTxSuccess(bool aTxStatus) { mIndirectTxSuccess = aTxStatus; }
108 
IsIndirectSourceMatchShort(void) const109         bool IsIndirectSourceMatchShort(void) const { return mUseShortAddress; }
SetIndirectSourceMatchShort(bool aShort)110         void SetIndirectSourceMatchShort(bool aShort) { mUseShortAddress = aShort; }
111 
IsIndirectSourceMatchPending(void) const112         bool IsIndirectSourceMatchPending(void) const { return mSourceMatchPending; }
SetIndirectSourceMatchPending(bool aPending)113         void SetIndirectSourceMatchPending(bool aPending) { mSourceMatchPending = aPending; }
114 
IncrementIndirectMessageCount(void)115         void IncrementIndirectMessageCount(void) { mQueuedMessageCount++; }
DecrementIndirectMessageCount(void)116         void DecrementIndirectMessageCount(void) { mQueuedMessageCount--; }
ResetIndirectMessageCount(void)117         void ResetIndirectMessageCount(void) { mQueuedMessageCount = 0; }
118 
IsWaitingForMessageUpdate(void) const119         bool IsWaitingForMessageUpdate(void) const { return mWaitingForMessageUpdate; }
SetWaitingForMessageUpdate(bool aNeedsUpdate)120         void SetWaitingForMessageUpdate(bool aNeedsUpdate) { mWaitingForMessageUpdate = aNeedsUpdate; }
121 
122         const Mac::Address &GetMacAddress(Mac::Address &aMacAddress) const;
123 
124         Message *mIndirectMessage;             // Current indirect message.
125         uint16_t mIndirectFragmentOffset : 14; // 6LoWPAN fragment offset for the indirect message.
126         bool     mIndirectTxSuccess : 1;       // Indicates tx success/failure of current indirect message.
127         bool     mWaitingForMessageUpdate : 1; // Indicates waiting for updating the indirect message.
128         uint16_t mQueuedMessageCount : 14;     // Number of queued indirect messages for the child.
129         bool     mUseShortAddress : 1;         // Indicates whether to use short or extended address.
130         bool     mSourceMatchPending : 1;      // Indicates whether or not pending to add to src match table.
131 
132         static_assert(OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS < (1UL << 14),
133                       "mQueuedMessageCount cannot fit max required!");
134     };
135 
136     /**
137      * This constructor initializes the object.
138      *
139      * @param[in]  aInstance  A reference to the OpenThread instance.
140      *
141      */
142     explicit IndirectSender(Instance &aInstance);
143 
144     /**
145      * This method enables indirect transmissions.
146      *
147      */
Start(void)148     void Start(void) { mEnabled = true; }
149 
150     /**
151      * This method disables indirect transmission.
152      *
153      * Any previously scheduled indirect transmission is canceled.
154      *
155      */
156     void Stop(void);
157 
158     /**
159      * This method adds a message for indirect transmission to a sleepy child.
160      *
161      * @param[in] aMessage  The message to add.
162      * @param[in] aChild    The (sleepy) child for indirect transmission.
163      *
164      */
165     void AddMessageForSleepyChild(Message &aMessage, Child &aChild);
166 
167     /**
168      * This method removes a message for indirect transmission to a sleepy child.
169      *
170      * @param[in] aMessage  The message to update.
171      * @param[in] aChild    The (sleepy) child for indirect transmission.
172      *
173      * @retval kErrorNone          Successfully removed the message for indirect transmission.
174      * @retval kErrorNotFound      The message was not scheduled for indirect transmission to the child.
175      *
176      */
177     Error RemoveMessageFromSleepyChild(Message &aMessage, Child &aChild);
178 
179     /**
180      * This method removes all added messages for a specific child and frees message (with no indirect/direct tx).
181      *
182      * @param[in]  aChild  A reference to a child whose messages shall be removed.
183      *
184      */
185     void ClearAllMessagesForSleepyChild(Child &aChild);
186 
187     /**
188      * This method sets whether to use the extended or short address for a child.
189      *
190      * @param[in] aChild            A reference to the child.
191      * @param[in] aUseShortAddress  `true` to use short address, `false` to use extended address.
192      *
193      */
194     void SetChildUseShortAddress(Child &aChild, bool aUseShortAddress);
195 
196     /**
197      * This method handles a child mode change and updates any queued messages for the child accordingly.
198      *
199      * @param[in]  aChild    The child whose device mode was changed.
200      * @param[in]  aOldMode  The old device mode of the child.
201      *
202      */
203     void HandleChildModeChange(Child &aChild, Mle::DeviceMode aOldMode);
204 
205 private:
206     /**
207      * Indicates whether to set/enable 15.4 ack request in the MAC header of a supervision message.
208      *
209      */
210     static constexpr bool kSupervisionMsgAckRequest = (OPENTHREAD_CONFIG_CHILD_SUPERVISION_MSG_NO_ACK_REQUEST == 0);
211 
212     // Callbacks from DataPollHandler
213     Error PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild);
214     void  HandleSentFrameToChild(const Mac::TxFrame &aFrame, const FrameContext &aContext, Error aError, Child &aChild);
215     void  HandleFrameChangeDone(Child &aChild);
216 
217     void     UpdateIndirectMessage(Child &aChild);
218     Message *FindIndirectMessage(Child &aChild, bool aSupervisionTypeOnly = false);
219     void     RequestMessageUpdate(Child &aChild);
220     uint16_t PrepareDataFrame(Mac::TxFrame &aFrame, Child &aChild, Message &aMessage);
221     void     PrepareEmptyFrame(Mac::TxFrame &aFrame, Child &aChild, bool aAckRequest);
222     void     ClearMessagesForRemovedChildren(void);
223 
224     bool                  mEnabled;
225     SourceMatchController mSourceMatchController;
226     DataPollHandler       mDataPollHandler;
227 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
228     CslTxScheduler mCslTxScheduler;
229 #endif
230 };
231 
232 /**
233  * @}
234  *
235  */
236 
237 } // namespace ot
238 
239 #endif // OPENTHREAD_FTD
240 
241 #endif // INDIRECT_SENDER_HPP_
242