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  * @brief
32  *   This file defines the mac frame interface for OpenThread platform radio drivers.
33  */
34 
35 #ifndef OPENTHREAD_UTILS_MAC_FRAME_H
36 #define OPENTHREAD_UTILS_MAC_FRAME_H
37 
38 #include <openthread/platform/radio.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /**
45  * Specifies the IEEE 802.15.4 Address type.
46  */
47 typedef enum
48 {
49     OT_MAC_ADDRESS_TYPE_NONE,     ///< No address.
50     OT_MAC_ADDRESS_TYPE_SHORT,    ///< IEEE 802.15.4 Short Address.
51     OT_MAC_ADDRESS_TYPE_EXTENDED, ///< IEEE 802.15.4 Extended Address.
52 } otMacAddressType;
53 
54 /**
55  * Represents an IEEE 802.15.4 short or extended Address.
56  */
57 typedef struct otMacAddress
58 {
59     union
60     {
61         otShortAddress mShortAddress; ///< The IEEE 802.15.4 Short Address.
62         otExtAddress   mExtAddress;   ///< The IEEE 802.15.4 Extended Address.
63     } mAddress;
64 
65     otMacAddressType mType; ///< The address type (short, extended, or none).
66 } otMacAddress;
67 
68 /**
69  * Check if @p aFrame is an Ack frame.
70  *
71  * @param[in]   aFrame          A pointer to the frame.
72  *
73  * @retval  true    It is an ACK frame.
74  * @retval  false   It is not an ACK frame.
75  */
76 bool otMacFrameIsAck(const otRadioFrame *aFrame);
77 
78 /**
79  * Check if @p aFrame is a Data frame.
80  *
81  * @param[in]   aFrame          A pointer to the frame.
82  *
83  * @retval  true    It is a Data frame.
84  * @retval  false   It is not a Data frame.
85  */
86 bool otMacFrameIsData(const otRadioFrame *aFrame);
87 
88 /**
89  * Check if @p aFrame is a Command frame.
90  *
91  * @param[in]   aFrame          A pointer to the frame.
92  *
93  * @retval  true    It is a Command frame.
94  * @retval  false   It is not a Command frame.
95  */
96 bool otMacFrameIsCommand(const otRadioFrame *aFrame);
97 
98 /**
99  * Check if @p aFrame is a Data Request Command.
100  *
101  * @param[in]   aFrame          A pointer to the frame. For 802.15.4-2015 and above frame,
102  *                              the frame should be already decrypted.
103  *
104  * @retval  true    It is a Data Request Command frame.
105  * @retval  false   It is not a Data Request Command frame.
106  */
107 bool otMacFrameIsDataRequest(const otRadioFrame *aFrame);
108 
109 /**
110  * Check if @p aFrame requests ACK.
111  *
112  * @param[in]   aFrame          A pointer to the frame.
113  *
114  * @retval  true    It requests ACK.
115  * @retval  false   It does not request ACK.
116  */
117 bool otMacFrameIsAckRequested(const otRadioFrame *aFrame);
118 
119 /**
120  * Check if @p aFrame matches the @p aPandId and @p aShortAddress or @p aExtAddress.
121  *
122  * @param[in]   aFrame          A pointer to the frame.
123  * @param[in]   aPanId          The PAN id to match with.
124  * @param[in]   aShortAddress   The short address to match with.
125  * @param[in]   aExtAddress     The extended address to match with.
126  *
127  * @retval  true    It is a broadcast or matches with the PAN id and one of the addresses.
128  * @retval  false   It doesn't match.
129  */
130 bool otMacFrameDoesAddrMatch(const otRadioFrame *aFrame,
131                              otPanId             aPanId,
132                              otShortAddress      aShortAddress,
133                              const otExtAddress *aExtAddress);
134 
135 /**
136  * Check if @p aFrame matches the @p aPandId and @p aShortAddress, or @p aAltShortAddress or @p aExtAddress.
137  *
138  * @param[in]   aFrame            A pointer to the frame.
139  * @param[in]   aPanId            The PAN id to match with.
140  * @param[in]   aShortAddress     The short address to match with.
141  * @param[in]   aAltShortAddress  The alternate short address to match with. Can be `OT_RADIO_INVALID_SHORT_ADDR` if
142  *                                there is no alternate address.
143  * @param[in]   aExtAddress       The extended address to match with.
144  *
145  * @retval  true    It is a broadcast or matches with the PAN id and one of the addresses.
146  * @retval  false   It doesn't match.
147  */
148 bool otMacFrameDoesAddrMatchAny(const otRadioFrame *aFrame,
149                                 otPanId             aPanId,
150                                 otShortAddress      aShortAddress,
151                                 otShortAddress      aAltShortAddress,
152                                 const otExtAddress *aExtAddress);
153 
154 /**
155  * Get source MAC address.
156  *
157  * @param[in]   aFrame          A pointer to the frame.
158  * @param[out]  aMacAddress     A pointer to MAC address.
159  *
160  * @retval  OT_ERROR_NONE   Successfully got the source MAC address.
161  * @retval  OT_ERROR_PARSE  Failed to parse the source MAC address.
162  */
163 otError otMacFrameGetSrcAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress);
164 
165 /**
166  * Get destination MAC address.
167  *
168  * @param[in]   aFrame          A pointer to the frame.
169  * @param[out]  aMacAddress     A pointer to MAC address.
170  *
171  * @retval  OT_ERROR_NONE   Successfully got the destination MAC address.
172  * @retval  OT_ERROR_PARSE  Failed to parse the destination MAC address.
173  */
174 otError otMacFrameGetDstAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress);
175 
176 /**
177  * Get the sequence of @p aFrame.
178  *
179  * @param[in]   aFrame          A pointer to the frame.
180  * @param[out]  aSequence       A pointer to the sequence.
181  *
182  * @retval  OT_ERROR_NONE   Successfully got the sequence.
183  * @retval  OT_ERROR_PARSE  Failed to parse the sequence.
184  */
185 otError otMacFrameGetSequence(const otRadioFrame *aFrame, uint8_t *aSequence);
186 
187 /**
188  * Performs AES CCM on the frame which is going to be sent.
189  *
190  * @param[in]  aFrame       A pointer to the MAC frame buffer that is going to be sent.
191  * @param[in]  aExtAddress  A pointer to the extended address, which will be used to generate nonce
192  *                          for AES CCM computation.
193  */
194 void otMacFrameProcessTransmitAesCcm(otRadioFrame *aFrame, const otExtAddress *aExtAddress);
195 
196 /**
197  * Tell if the version of @p aFrame is 2015.
198  *
199  * @param[in]   aFrame          A pointer to the frame.
200  *
201  * @retval  true    It is a version 2015 frame.
202  * @retval  false   It is not a version 2015 frame.
203  */
204 bool otMacFrameIsVersion2015(const otRadioFrame *aFrame);
205 
206 /**
207  * Generate Imm-Ack for @p aFrame.
208  *
209  * @param[in]    aFrame             A pointer to the frame.
210  * @param[in]    aIsFramePending    Value of the ACK's frame pending bit.
211  * @param[out]   aAckFrame          A pointer to the ack frame to be generated.
212  */
213 void otMacFrameGenerateImmAck(const otRadioFrame *aFrame, bool aIsFramePending, otRadioFrame *aAckFrame);
214 
215 /**
216  * Generate Enh-Ack for @p aFrame.
217  *
218  * @param[in]    aFrame             A pointer to the frame.
219  * @param[in]    aIsFramePending    Value of the ACK's frame pending bit.
220  * @param[in]    aIeData            A pointer to the IE data portion of the ACK to be sent.
221  * @param[in]    aIeLength          The length of IE data portion of the ACK to be sent.
222  * @param[out]   aAckFrame          A pointer to the ack frame to be generated.
223  *
224  * @retval  OT_ERROR_NONE           Successfully generated Enh Ack in @p aAckFrame.
225  * @retval  OT_ERROR_PARSE          @p aFrame has incorrect format.
226  */
227 otError otMacFrameGenerateEnhAck(const otRadioFrame *aFrame,
228                                  bool                aIsFramePending,
229                                  const uint8_t      *aIeData,
230                                  uint8_t             aIeLength,
231                                  otRadioFrame       *aAckFrame);
232 
233 /**
234  * Set CSL IE content into the frame.
235  *
236  * @param[in,out]   aFrame         A pointer to the frame to be modified.
237  * @param[in]       aCslPeriod     CSL Period in CSL IE.
238  * @param[in]       aCslPhase      CSL Phase in CSL IE.
239  */
240 void otMacFrameSetCslIe(otRadioFrame *aFrame, uint16_t aCslPeriod, uint16_t aCslPhase);
241 
242 /**
243  * Tell if the security of @p aFrame is enabled.
244  *
245  * @param[in]   aFrame          A pointer to the frame.
246  *
247  * @retval  true    The frame has security enabled.
248  * @retval  false   The frame does not have security enabled.
249  */
250 bool otMacFrameIsSecurityEnabled(otRadioFrame *aFrame);
251 
252 /**
253  * Tell if the key ID mode of @p aFrame is 1.
254  *
255  * @param[in]   aFrame          A pointer to the frame.
256  *
257  * @retval  true    The frame key ID mode is 1.
258  * @retval  false   The frame security is not enabled or key ID mode is not 1.
259  */
260 bool otMacFrameIsKeyIdMode1(otRadioFrame *aFrame);
261 
262 /**
263  * Tell if the key ID mode of @p aFrame is 2.
264  *
265  * @param[in]   aFrame          A pointer to the frame.
266  *
267  * @retval  true    The frame key ID mode is 2.
268  * @retval  false   The frame security is not enabled or key ID mode is not 2.
269  */
270 bool otMacFrameIsKeyIdMode2(otRadioFrame *aFrame);
271 
272 /**
273  * Get the key ID of @p aFrame.
274  *
275  * @param[in]   aFrame          A pointer to the frame.
276  *
277  * @returns The key ID of the frame with key ID mode 1. Returns 0 if failed.
278  */
279 uint8_t otMacFrameGetKeyId(otRadioFrame *aFrame);
280 
281 /**
282  * Set key ID to @p aFrame with key ID mode 1.
283  *
284  * @param[in,out]   aFrame     A pointer to the frame to be modified.
285  * @param[in]       aKeyId     Key ID to be set to the frame.
286  */
287 void otMacFrameSetKeyId(otRadioFrame *aFrame, uint8_t aKeyId);
288 
289 /**
290  * Get the frame counter of @p aFrame.
291  *
292  * @param[in]   aFrame          A pointer to the frame.
293  *
294  * @returns The frame counter of the frame. Returns UINT32_MAX if failed.
295  */
296 uint32_t otMacFrameGetFrameCounter(otRadioFrame *aFrame);
297 
298 /**
299  * Set frame counter to @p aFrame.
300  *
301  * @param[in,out]   aFrame         A pointer to the frame to be modified.
302  * @param[in]       aFrameCounter  Frame counter to be set to the frame.
303  */
304 void otMacFrameSetFrameCounter(otRadioFrame *aFrame, uint32_t aFrameCounter);
305 
306 /**
307  * Write CSL IE to a buffer (without setting IE value).
308  *
309  * @param[out]  aDest    A pointer to the output buffer.
310  *
311  * @returns  The total count of bytes (total length of CSL IE) written to the buffer.
312  */
313 uint8_t otMacFrameGenerateCslIeTemplate(uint8_t *aDest);
314 
315 /**
316  * Write Enh-ACK Probing IE (Vendor IE with THREAD OUI) to a buffer.
317  *
318  * @p aIeData could be `NULL`. If @p aIeData is `NULL`, this method generates the IE with the data unset. This allows
319  * users to generate the pattern first and update value later. (For example, using `otMacFrameSetEnhAckProbingIe`)
320  *
321  * @param[out]  aDest          A pointer to the output buffer.
322  * @param[in]   aIeData        A pointer to the Link Metrics data.
323  * @param[in]   aIeDataLength  The length of Link Metrics data value. Should be `1` or `2`. (Per spec 4.11.3.4.4.6)
324  *
325  * @returns  The total count of bytes (total length of the Vendor IE) written to the buffer.
326  */
327 uint8_t otMacFrameGenerateEnhAckProbingIe(uint8_t *aDest, const uint8_t *aIeData, uint8_t aIeDataLength);
328 
329 /**
330  * Sets the data value of Enh-ACK Probing IE (Vendor IE with THREAD OUI) in a frame.
331  *
332  * If no Enh-ACK Probing IE is found in @p aFrame, nothing would be done.
333  *
334  * @param[in]  aFrame    The target frame that contains the IE. MUST NOT be `NULL`.
335  * @param[in]  aData     A pointer to the data value. MUST NOT be `NULL`.
336  * @param[in]  aDataLen  The length of @p aData.
337  */
338 void otMacFrameSetEnhAckProbingIe(otRadioFrame *aFrame, const uint8_t *aData, uint8_t aDataLen);
339 
340 /**
341  * Represents the context for radio layer.
342  */
343 typedef struct otRadioContext
344 {
345     otExtAddress     mExtAddress; ///< In little-endian byte order.
346     uint32_t         mMacFrameCounter;
347     uint32_t         mPrevMacFrameCounter;
348     uint32_t         mCslSampleTime; ///< The sample time based on the microsecond timer.
349     uint16_t         mCslPeriod;     ///< In unit of 10 symbols.
350     otShortAddress   mShortAddress;
351     otShortAddress   mAlternateShortAddress;
352     otRadioKeyType   mKeyType;
353     uint8_t          mKeyId;
354     otMacKeyMaterial mPrevKey;
355     otMacKeyMaterial mCurrKey;
356     otMacKeyMaterial mNextKey;
357 } otRadioContext;
358 
359 /**
360  * Perform processing of SFD callback from ISR.
361  *
362  * This function may do multiple tasks as follows.
363  *
364  *  - CSL IE will be populated (if present)
365  *  - Time IE will be populated (if present)
366  *  - Tx timestamp will be populated
367  *  - Tx security will be performed (including assignment of security frame counter and key id if not assigned)
368  *
369  * @param[in,out]   aFrame          The target frame. MUST NOT be `NULL`.
370  * @param[in]       aRadioTime      The radio time when the SFD was at the antenna.
371  * @param[in,out]   aRadioContext   The radio context accessible in ISR.
372  *
373  * @returns the error processing the callback. The caller should abort transmission on failures.
374  */
375 otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioContext *aRadioContext);
376 
377 /**
378  * Process frame tx security.
379  *
380  * @param[in,out]   aFrame          The target frame. MUST NOT be `NULL`.
381  * @param[in,out]   aRadioContext   The radio context accessible in ISR.
382  *
383  * @retval OT_ERROR_NONE     Successfully processed security.
384  * @retval OT_ERROR_FAILED   Failed to processed security.
385  * @retval OT_ERROR_SECURITY Failed to processed security for missing key.
386  */
387 otError otMacFrameProcessTransmitSecurity(otRadioFrame *aFrame, otRadioContext *aRadioContext);
388 
389 #ifdef __cplusplus
390 } // extern "C"
391 #endif
392 
393 #endif // OPENTHREAD_UTILS_MAC_FRAME_H
394