• 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 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