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 Thread Radio Encapsulation Link (TREL) Packet
32  */
33 
34 #ifndef TREL_PACKET_HPP_
35 #define TREL_PACKET_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
40 
41 #include "common/encoding.hpp"
42 #include "common/locator.hpp"
43 #include "common/string.hpp"
44 #include "mac/mac_types.hpp"
45 
46 namespace ot {
47 namespace Trel {
48 
49 /**
50  * This class represents a TREL radio link packet encapsulation header.
51  *
52  */
53 OT_TOOL_PACKED_BEGIN
54 class Header
55 {
56 public:
57     /**
58      * This enumeration defines packet types.
59      *
60      */
61     enum Type : uint8_t
62     {
63         kTypeBroadcast = 0, ///< A TREL broadcast packet.
64         kTypeUnicast   = 1, ///< A TREL unicast packet.
65         kTypeAck       = 2, ///< A TREL Ack packet.
66     };
67 
68     /**
69      * This enumeration represents Ack Mode field in TREL header.
70      *
71      */
72     enum AckMode : uint8_t
73     {
74         kNoAck,        ///< No TREL Ack is requested.
75         kAckRequested, ///< A TREL Ack is requested.
76     };
77 
78     static constexpr uint16_t kInfoStringSize = 128; ///< Max chars for the info string (@sa ToInfoString()).
79 
80     /**
81      * This type defines the fixed-length `String` object returned from `ToString()` method.
82      *
83      */
84     typedef String<kInfoStringSize> InfoString;
85 
86     /**
87      * This method initializes the header.
88      *
89      * @param[in] aType     The header type.
90      *
91      */
Init(Type aType)92     void Init(Type aType) { mControl = aType + kVersion; }
93 
94     /**
95      * This method checks whether the version field in header is valid or not
96      *
97      * @returns TRUE if the version field is valid, FALSE otherwise.
98      *
99      */
IsVersionValid(void) const100     bool IsVersionValid(void) const { return (mControl & kVersionMask) == kVersion; }
101 
102     /**
103      * This method gets the packet type.
104      *
105      * @returns The packet type.
106      *
107      */
GetType(void) const108     Type GetType(void) const { return static_cast<Type>(mControl & kTypeMask); }
109 
110     /**
111      * This method gets the header length based on its type.
112      *
113      * @returns the header length (number of bytes).
114      *
115      */
GetLength(void) const116     uint16_t GetLength(void) const { return GetSize(GetType()); }
117 
118     /**
119      * This method gets the Ack Mode field from the header.
120      *
121      * @returns The Ack Mode field.
122      *
123      */
GetAckMode(void) const124     AckMode GetAckMode(void) const { return (mControl & kAckModeFlag) ? kAckRequested : kNoAck; }
125 
126     /**
127      * This method sets the Ack Mode field in the header.
128      *
129      * @param[in] aAckMode  The Ack Mode field
130      *
131      */
132     void SetAckMode(AckMode aAckMode);
133 
134     /**
135      * This method gets the channel field from the header.
136      *
137      * @returns The channel field.
138      *
139      */
GetChannel(void) const140     uint8_t GetChannel(void) const { return mChannel; }
141 
142     /**
143      * This method sets the channel field in the header.
144      *
145      * @param[in] aChannel   A channel.
146      *
147      */
SetChannel(uint8_t aChannel)148     void SetChannel(uint8_t aChannel) { mChannel = aChannel; }
149 
150     /**
151      * This method gets the PAN Identifier field from the header.
152      *
153      * @returns The PAN Identifier field.
154      *
155      */
GetPanId(void) const156     Mac::PanId GetPanId(void) const { return Encoding::BigEndian::HostSwap16(mPanId); }
157 
158     /**
159      * This method sets the PAN Identifier field in the header.
160      *
161      * @param[in] aPanId   A PAN Identifier.
162      *
163      */
SetPanId(Mac::PanId aPanId)164     void SetPanId(Mac::PanId aPanId) { mPanId = Encoding::BigEndian::HostSwap16(aPanId); }
165 
166     /**
167      * This method gets the packet number field from the header.
168      *
169      * @returns The packet number field.
170      *
171      */
GetPacketNumber(void) const172     uint32_t GetPacketNumber(void) const { return Encoding::BigEndian::HostSwap32(mPacketNumber); }
173 
174     /**
175      * This method sets the packet number field in the header.
176      *
177      * @param[in] aPacketNumber  The packet number.
178      *
179      */
SetPacketNumber(uint32_t aPacketNumber)180     void SetPacketNumber(uint32_t aPacketNumber) { mPacketNumber = Encoding::BigEndian::HostSwap32(aPacketNumber); }
181 
182     /**
183      * This method gets the source MAC address field from the header.
184      *
185      * @returns The source MAC address field.
186      *
187      */
GetSource(void) const188     const Mac::ExtAddress &GetSource(void) const { return mSource; }
189 
190     /**
191      * This method sets the source MAC address filed in the header.
192      *
193      * @param[in] aSource   A MAC extended address to set as source.
194      *
195      */
SetSource(const Mac::ExtAddress & aSource)196     void SetSource(const Mac::ExtAddress &aSource) { mSource = aSource; }
197 
198     /**
199      * This method gets the destination MAC address field from the header.
200      *
201      * This method MUST be used with a unicast of ack type packet, otherwise its behavior is undefined.
202      *
203      * @returns The destination MAC address field.
204      *
205      */
GetDestination(void) const206     const Mac::ExtAddress &GetDestination(void) const { return mDestination; }
207 
208     /**
209      * This method sets the destination MAC address field in the header.
210      *
211      * This method MUST be used with a unicast of ack type packet, otherwise its behavior is undefined.
212      *
213      * @param[in] aDest   A MAC extended address to set as destination.
214      *
215      */
SetDestination(const Mac::ExtAddress & aDest)216     void SetDestination(const Mac::ExtAddress &aDest) { mDestination = aDest; }
217 
218     /**
219      * This static method gets the size (number of bytes) in header of given packet type.
220      *
221      * @param[in] aType   The packet type.
222      *
223      * @returns The fixed header size (number of bytes) for @p aType packet.
224      *
225      */
226     static uint16_t GetSize(Type aType);
227 
228     /**
229      * This method returns a string representation of header.
230      *
231      * @returns An `InfoString` representation of header.
232      *
233      */
234     InfoString ToString(void) const;
235 
236 private:
237     static constexpr uint8_t kTypeMask    = (3 << 0); // Bits 0-1 specify packet `Type`
238     static constexpr uint8_t kAckModeFlag = (1 << 2); // Bit 2 indicate "ack mode" (TREL ack requested or not).
239     static constexpr uint8_t kVersionMask = (7 << 5); // Bits 5-7 specify the version.
240     static constexpr uint8_t kVersion     = (0 << 5); // Current TREL header version.
241 
242     // All header fields are big-endian.
243 
244     uint8_t         mControl;
245     uint8_t         mChannel;
246     uint16_t        mPanId;
247     uint32_t        mPacketNumber;
248     Mac::ExtAddress mSource;
249     Mac::ExtAddress mDestination; // Present in `kTypeAck` or `kTypeUnicast` packet types.
250 } OT_TOOL_PACKED_END;
251 
252 /**
253  * This class represent a TREL radio link packet.
254  *
255  */
256 class Packet
257 {
258 public:
259     /**
260      * This method initializes the `Packet` with a given buffer and length.
261      *
262      * @param[in] aBuffer  A pointer to a buffer containing the entire packet (header and payload).
263      * @param[in] aLength  Length (number of bytes) of the packet (including header and payload).
264      *
265      */
266     void Init(uint8_t *aBuffer, uint16_t aLength);
267 
268     /**
269      * This method initializes the `Packet` with a specified header type and given a payload.
270      *
271      * The payload buffer @p aPayload should have space reserved before the start of payload for the packet header.
272      * This method will initialize the header with the given type @p aType. Rest of header fields can be updated after
273      * initializing the packet.
274      *
275      * @param[in] aType          The packet type.
276      * @param[in] aPayload       A pointer to a buffer containing the packet payload. Buffer should have space reserved
277      *                           for header before the payload.
278      * @param[in] aPayloadLength The length (number of bytes) in the payload only (not including the header).
279      *
280      */
281     void Init(Header::Type aType, uint8_t *aPayload, uint16_t aPayloadLength);
282 
283     /**
284      * This method gets a pointer to buffer containing the packet.
285      *
286      * @returns A pointer to buffer containing the packet.
287      *
288      */
GetBuffer(void)289     uint8_t *GetBuffer(void) { return mBuffer; }
290 
291     /**
292      * This method gets a pointer to buffer containing the packet.
293      *
294      * @returns A pointer to buffer containing the packet.
295      *
296      */
GetBuffer(void) const297     const uint8_t *GetBuffer(void) const { return mBuffer; }
298 
299     /**
300      * This method gets the length of packet.
301      *
302      * @returns The length (number of bytes) of packet (header and payload).
303      *
304      */
GetLength(void) const305     uint16_t GetLength(void) const { return mLength; }
306 
307     /**
308      * This method checks whether or not the packet header is valid.
309      *
310      * @retval TRUE   The packet header is valid and well-formed.
311      * @retval FALSE  The packet header is not valid.
312      *
313      */
314     bool IsHeaderValid(void) const;
315 
316     /**
317      * This method gets the packet header.
318      *
319      * @returns A reference to the packet header as `Header`.
320      *
321      */
GetHeader(void)322     Header &GetHeader(void) { return *reinterpret_cast<Header *>(mBuffer); }
323 
324     /**
325      * This method gets the packet header.
326      *
327      * @returns A reference to the packet header as `Header`.
328      *
329      */
GetHeader(void) const330     const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mBuffer); }
331 
332     /**
333      * This method gets a pointer to start of packet payload.
334      *
335      * @returns A pointer to start of packet payload (after header).
336      *
337      */
GetPayload(void)338     uint8_t *GetPayload(void) { return mBuffer + GetHeader().GetLength(); }
339 
340     /**
341      * This method gets a pointer to start of packet payload.
342      *
343      * @returns A pointer to start of packet payload (after header).
344      *
345      */
GetPayload(void) const346     const uint8_t *GetPayload(void) const { return mBuffer + GetHeader().GetLength(); }
347 
348     /**
349      * This method gets the payload length.
350      *
351      * @returns The packet payload length (number of bytes).
352      *
353      */
GetPayloadLength(void) const354     uint16_t GetPayloadLength(void) const { return mLength - GetHeader().GetLength(); }
355 
356 private:
357     uint8_t *mBuffer;
358     uint16_t mLength;
359 };
360 
361 } // namespace Trel
362 } // namespace ot
363 
364 #endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
365 
366 #endif // TREL_PACKET_HPP_
367