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 radio selector (for multi radio links).
32  */
33 
34 #ifndef RADIO_SELECTOR_HPP_
35 #define RADIO_SELECTOR_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_CONFIG_MULTI_RADIO
40 
41 #include <openthread/multi_radio.h>
42 
43 #include "common/locator.hpp"
44 #include "common/message.hpp"
45 #include "mac/mac_frame.hpp"
46 #include "mac/mac_links.hpp"
47 #include "mac/mac_types.hpp"
48 
49 namespace ot {
50 
51 /**
52  * @addtogroup core-radio-selector
53  *
54  * @brief
55  *   This module includes definition for radio selector (for multi radio links).
56  *
57  * @{
58  *
59  */
60 
61 class Neighbor;
62 
63 class RadioSelector : InstanceLocator
64 {
65 public:
66     /**
67      * This class defines all the neighbor info required for multi radio link and radio selection.
68      *
69      * `Neighbor` class publicly inherits from this class.
70      *
71      */
72     class NeighborInfo
73     {
74         friend class RadioSelector;
75 
76     public:
77         /**
78          * This type represents multi radio information associated with a neighbor.
79          *
80          */
81         typedef otMultiRadioNeighborInfo MultiRadioInfo;
82 
83         /**
84          * This method returns the supported radio types by the neighbor.
85          *
86          * @returns The supported radio types set.
87          *
88          */
GetSupportedRadioTypes(void) const89         Mac::RadioTypes GetSupportedRadioTypes(void) const { return mSupportedRadioTypes; }
90 
91         /**
92          * This method retrieves the multi radio information `otMultiRadioNeighborInfo` associated with the neighbor.
93          *
94          * @param[out] aInfo  A reference to `MultiRadioInfo` to populate with neighbor info.
95          *
96          */
97         void PopulateMultiRadioInfo(MultiRadioInfo &aInfo);
98 
99     private:
AddSupportedRadioType(Mac::RadioType aType)100         void AddSupportedRadioType(Mac::RadioType aType) { mSupportedRadioTypes.Add(aType); }
RemoveSupportedRadioType(Mac::RadioType aType)101         void RemoveSupportedRadioType(Mac::RadioType aType) { mSupportedRadioTypes.Remove(aType); }
ClearSupportedRadioType(void)102         void ClearSupportedRadioType(void) { mSupportedRadioTypes.Clear(); }
103 
GetRadioPreference(Mac::RadioType aType) const104         uint8_t GetRadioPreference(Mac::RadioType aType) const { return mRadioPreference[aType]; }
SetRadioPreference(Mac::RadioType aType,uint8_t aValue)105         void    SetRadioPreference(Mac::RadioType aType, uint8_t aValue) { mRadioPreference[aType] = aValue; }
106 
107         Mac::RadioTypes mSupportedRadioTypes;
108         uint8_t         mRadioPreference[Mac::kNumRadioTypes];
109     };
110 
111     /**
112      * This constructor initializes the RadioSelector object.
113      *
114      * @param[in]  aInstance     A reference to the OpenThread instance.
115      *
116      */
117     explicit RadioSelector(Instance &aInstance);
118 
119     /**
120      * This method updates the neighbor info (for multi radio support) on a received frame event.
121      *
122      * This method notifies `RadioSelector` of a received secure frame/message on a radio link type for neighbor. If
123      * the frame/message happens to be received earlier on another radio link, the `aIsDuplicate` is set to `true`.
124      * A duplicate frame/message should have passed the security check (i.e., tag/MIC should be valid).
125      *
126      * @param[in] aNeighbor     The neighbor for which a frame/message was received.
127      * @param[in] aRadioType    The radio link type on which the frame/message was received.
128      * @param[in] aIsDuplicate  Indicates whether the received frame/message is a duplicate or not.
129      *
130      */
131     void UpdateOnReceive(Neighbor &aNeighbor, Mac::RadioType aRadioType, bool aIsDuplicate);
132 
133     /**
134      * This method updates the neighbor info (for multi radio support) on a send done event.
135      *
136      * This method notifies `RadioSelector` the status of frame transmission on a radio link type. The radio link
137      * type is provided by the `aFrame` itself.
138      *
139      * @param[in] aFrame     A transmitted frame.
140      * @param[in] aTxError   The transmission error.
141      *
142      */
143     void UpdateOnSendDone(Mac::TxFrame &aFrame, Error aTxError);
144 
145 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
146     /**
147      * This method updates the neighbor info (for multi radio support) on a deferred ack event.
148      *
149      * The deferred ack model is used by TREL radio link.
150      *
151      * @param[in]  aNeighbor              The neighbor from which ack was expected
152      * @param[in]  aError                 The deferred ack status (`kErrorNone` indicates ack was received).
153      * @param[out] aAllowNeighborRemove   Boolean variable to output whether the neighbor is allowed to be removed.
154      *
155      */
156     void UpdateOnDeferredAck(Neighbor &aNeighbor, Error aTxError, bool &aAllowNeighborRemove);
157 #endif
158 
159     /**
160      * This method selects the radio link type for sending a data poll frame to a given parent neighbor.
161      *
162      * @param[in] aParent  The parent to which the data poll frame will be sent.
163      *
164      * @returns The radio type on which the data poll frame should be sent.
165      *
166      */
167     Mac::RadioType SelectPollFrameRadio(const Neighbor &aParent);
168 
169     /**
170      * This method selects the radio link for sending a given message to a specified MAC destination.
171      *
172      * The `aMessage` will be updated to store the selected radio type (please see `Message::GetRadioType()`).
173      * The `aTxFrames` will also be updated to indicate which radio links are to be used.
174      *
175      * @param[inout] aMessage   The message to send.
176      * @param[in]    aMacDest   The MAC destination address.
177      * @param[inout] aTxFrames  The set of TxFrames for all radio links.
178      *
179      * @returns  A reference to `mTxFrame` to use when preparing the frame for tx.
180      *
181      */
182     Mac::TxFrame &SelectRadio(Message &aMessage, const Mac::Address &aMacDest, Mac::TxFrames &aTxFrames);
183 
184 private:
185     static constexpr int16_t kPreferenceChangeOnTxError            = -35;  // Change on a tx error on a radio link.
186     static constexpr int16_t kPreferenceChangeOnTxSuccess          = 25;   // Change on tx success on a radio link.
187     static constexpr int16_t kPreferenceChangeOnDeferredAckSuccess = 25;   // Change on deferred ack success.
188     static constexpr int16_t kPreferenceChangeOnDeferredAckTimeout = -100; // Change on deferred ack timeout.
189     static constexpr int16_t kPreferenceChangeOnRx                 = 15;   // Change on new (secure) rx.
190     static constexpr int16_t kPreferenceChangeOnRxDuplicate        = 15;   // Change on new (secure) duplicate rx.
191 
192     static constexpr uint8_t kMinPreference  = 0;   // Minimum preference value.
193     static constexpr uint8_t kMaxPreference  = 255; // Maximum preference value.
194     static constexpr uint8_t kInitPreference = 200; // Initial preference value
195     static constexpr uint8_t kHighPreference = 220; // High preference.
196 
197     static constexpr uint8_t kTrelProbeProbability = 25; // Probability percentage to probe on TREL link
198 
199     static constexpr uint16_t kRadioPreferenceStringSize = 75;
200 
201     otLogLevel     UpdatePreference(Neighbor &aNeighbor, Mac::RadioType aRadioType, int16_t aDifference);
202     Mac::RadioType Select(Mac::RadioTypes aRadioOptions, const Neighbor &aNeighbor);
203     void           Log(otLogLevel aLogLevel, const char *aActionText, Mac::RadioType aType, const Neighbor &aNeighbor);
204 
205     static const Mac::RadioType sRadioSelectionOrder[Mac::kNumRadioTypes];
206 };
207 
208 /**
209  * @}
210  *
211  */
212 
213 } // namespace ot
214 
215 #endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
216 
217 #endif // RADIO_SELECTOR_HPP_
218