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