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 implements the MAC radio links.
32 */
33
34 #include "mac_links.hpp"
35
36 #include "common/code_utils.hpp"
37 #include "common/instance.hpp"
38 #include "common/locator_getters.hpp"
39
40 namespace ot {
41 namespace Mac {
42
43 //---------------------------------------------------------------------------------------------------------------------
44 // TxFrames
45
TxFrames(Instance & aInstance)46 TxFrames::TxFrames(Instance &aInstance)
47 : InstanceLocator(aInstance)
48 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
49 , mTxFrame802154(aInstance.Get<SubMac>().GetTransmitFrame())
50 #endif
51 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
52 , mTxFrameTrel(aInstance.Get<Trel::Link>().GetTransmitFrame())
53 #endif
54 {
55 }
56
57 #if OPENTHREAD_CONFIG_MULTI_RADIO
58
GetTxFrame(RadioType aRadioType)59 TxFrame &TxFrames::GetTxFrame(RadioType aRadioType)
60 {
61 TxFrame *frame = nullptr;
62
63 switch (aRadioType)
64 {
65 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
66 case kRadioTypeIeee802154:
67 frame = &mTxFrame802154;
68 break;
69 #endif
70 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
71 case kRadioTypeTrel:
72 frame = &mTxFrameTrel;
73 break;
74 #endif
75 }
76
77 mSelectedRadioTypes.Add(aRadioType);
78
79 return *frame;
80 }
81
GetTxFrame(RadioTypes aRadioTypes)82 TxFrame &TxFrames::GetTxFrame(RadioTypes aRadioTypes)
83 {
84 // Return the TxFrame among all set of `aRadioTypes` with the smallest MTU.
85 // Note that this is `TxFrame` to be sent out in parallel over multiple radio
86 // radio links in `aRadioTypes, so we need to make sure that it fits in the
87 // most restricted radio link (with smallest MTU).
88
89 TxFrame *frame = nullptr;
90
91 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
92 if (aRadioTypes.Contains(kRadioTypeIeee802154))
93 {
94 frame = &mTxFrame802154;
95 }
96 #endif
97
98 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
99 if (aRadioTypes.Contains(kRadioTypeTrel) && ((frame == nullptr) || (frame->GetMtu() > mTxFrameTrel.GetMtu())))
100 {
101 frame = &mTxFrameTrel;
102 }
103 #endif
104
105 mSelectedRadioTypes.Add(aRadioTypes);
106
107 return *frame;
108 }
109
GetBroadcastTxFrame(void)110 TxFrame &TxFrames::GetBroadcastTxFrame(void)
111 {
112 RadioTypes allRadios;
113
114 allRadios.AddAll();
115 return GetTxFrame(allRadios);
116 }
117
118 #endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
119
120 //---------------------------------------------------------------------------------------------------------------------
121 // Links
122
Links(Instance & aInstance)123 Links::Links(Instance &aInstance)
124 : InstanceLocator(aInstance)
125 , mSubMac(aInstance)
126 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
127 , mTrel(aInstance)
128 #endif
129 , mTxFrames(aInstance)
130 #if !OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
131 , mShortAddress(kShortAddrInvalid)
132 #endif
133 {
134 #if !OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
135 mExtAddress.Clear();
136 #endif
137 }
138
139 #if OPENTHREAD_CONFIG_MULTI_RADIO
140
Send(TxFrame & aFrame,RadioTypes aRadioTypes)141 void Links::Send(TxFrame &aFrame, RadioTypes aRadioTypes)
142 {
143 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
144 if (aRadioTypes.Contains(kRadioTypeIeee802154) && mTxFrames.mTxFrame802154.IsEmpty())
145 {
146 mTxFrames.mTxFrame802154.CopyFrom(aFrame);
147 }
148 #endif
149 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
150 if (aRadioTypes.Contains(kRadioTypeTrel) && mTxFrames.mTxFrameTrel.IsEmpty())
151 {
152 mTxFrames.mTxFrameTrel.CopyFrom(aFrame);
153 }
154 #endif
155
156 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
157 if (aRadioTypes.Contains(kRadioTypeIeee802154))
158 {
159 SuccessOrAssert(mSubMac.Send());
160 }
161 #endif
162 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
163 if (aRadioTypes.Contains(kRadioTypeTrel))
164 {
165 mTrel.Send();
166 }
167 #endif
168 }
169
170 #endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
171
GetCurrentMacKey(const Frame & aFrame) const172 const KeyMaterial *Links::GetCurrentMacKey(const Frame &aFrame) const
173 {
174 // Gets the security MAC key (for Key Mode 1) based on radio link type of `aFrame`.
175
176 const KeyMaterial *key = nullptr;
177 #if OPENTHREAD_CONFIG_MULTI_RADIO
178 RadioType radioType = aFrame.GetRadioType();
179 #endif
180
181 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
182 #if OPENTHREAD_CONFIG_MULTI_RADIO
183 if (radioType == kRadioTypeIeee802154)
184 #endif
185 {
186 ExitNow(key = &Get<SubMac>().GetCurrentMacKey());
187 }
188 #endif
189
190 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
191 #if OPENTHREAD_CONFIG_MULTI_RADIO
192 if (radioType == kRadioTypeTrel)
193 #endif
194 {
195 ExitNow(key = &Get<KeyManager>().GetCurrentTrelMacKey());
196 }
197 #endif
198
199 OT_UNUSED_VARIABLE(aFrame);
200
201 exit:
202 return key;
203 }
204
GetTemporaryMacKey(const Frame & aFrame,uint32_t aKeySequence) const205 const KeyMaterial *Links::GetTemporaryMacKey(const Frame &aFrame, uint32_t aKeySequence) const
206 {
207 // Gets the security MAC key (for Key Mode 1) based on radio link
208 // type of `aFrame` and given Key Sequence.
209
210 const KeyMaterial *key = nullptr;
211 #if OPENTHREAD_CONFIG_MULTI_RADIO
212 RadioType radioType = aFrame.GetRadioType();
213 #endif
214
215 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
216 #if OPENTHREAD_CONFIG_MULTI_RADIO
217 if (radioType == kRadioTypeIeee802154)
218 #endif
219 {
220 if (aKeySequence == Get<KeyManager>().GetCurrentKeySequence() - 1)
221 {
222 ExitNow(key = &Get<SubMac>().GetPreviousMacKey());
223 }
224 else if (aKeySequence == Get<KeyManager>().GetCurrentKeySequence() + 1)
225 {
226 ExitNow(key = &Get<SubMac>().GetNextMacKey());
227 }
228 else
229 {
230 OT_ASSERT(false);
231 }
232 }
233 #endif
234
235 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
236 #if OPENTHREAD_CONFIG_MULTI_RADIO
237 if (radioType == kRadioTypeTrel)
238 #endif
239 {
240 ExitNow(key = &Get<KeyManager>().GetTemporaryTrelMacKey(aKeySequence));
241 }
242 #endif
243
244 OT_UNUSED_VARIABLE(aFrame);
245
246 exit:
247 return key;
248 }
249
250 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
SetMacFrameCounter(TxFrame & aFrame)251 void Links::SetMacFrameCounter(TxFrame &aFrame)
252 {
253 #if OPENTHREAD_CONFIG_MULTI_RADIO
254 RadioType radioType = aFrame.GetRadioType();
255 #endif
256
257 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
258 #if OPENTHREAD_CONFIG_MULTI_RADIO
259 if (radioType == kRadioTypeTrel)
260 #endif
261 {
262 aFrame.SetFrameCounter(Get<KeyManager>().GetTrelMacFrameCounter());
263 Get<KeyManager>().IncrementTrelMacFrameCounter();
264 ExitNow();
265 }
266 #endif
267
268 exit:
269 return;
270 }
271 #endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
272
273 } // namespace Mac
274 } // namespace ot
275