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