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).
32  */
33 
34 #ifndef TREL_LINK_HPP_
35 #define TREL_LINK_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/notifier.hpp"
44 #include "common/tasklet.hpp"
45 #include "common/timer.hpp"
46 #include "mac/mac_frame.hpp"
47 #include "mac/mac_types.hpp"
48 #include "radio/trel_interface.hpp"
49 #include "radio/trel_packet.hpp"
50 
51 namespace ot {
52 
53 class Neighbor;
54 
55 namespace Trel {
56 
57 /**
58  * @addtogroup core-trel
59  *
60  * @brief
61  *   This module includes definitions for Thread Radio Encapsulation Link (TREL)
62  *
63  * @{
64  *
65  */
66 
67 /**
68  * This class represents a Thread Radio Encapsulation Link (TREL).
69  *
70  */
71 class Link : public InstanceLocator
72 {
73     friend class ot::Instance;
74     friend class ot::Notifier;
75     friend class Interface;
76 
77 public:
78     static constexpr uint16_t kMtuSize = 1280 - 48 - sizeof(Header); ///< MTU size for TREL frame.
79     static constexpr uint8_t  kFcsSize = 0;                          ///< FCS size for TREL frame.
80 
81     /**
82      * This constructor initializes the `Link` object.
83      *
84      * @param[in]  aInstance  A reference to the OpenThread instance.
85      *
86      */
87     explicit Link(Instance &aInstance);
88 
89     /**
90      * This method sets the PAN Identifier.
91      *
92      * @param[in] aPanId   A PAN Identifier.
93      *
94      */
SetPanId(Mac::PanId aPanId)95     void SetPanId(Mac::PanId aPanId) { mPanId = aPanId; }
96 
97     /**
98      * This method notifies TREL radio link that device's extended MAC address has changed for it to update any
99      * internal address/state.
100      *
101      */
HandleExtAddressChange(void)102     void HandleExtAddressChange(void) { mInterface.HandleExtAddressChange(); }
103 
104     /**
105      * This method enables the TREL radio link.
106      *
107      */
108     void Enable(void);
109 
110     /**
111      * This method disables the TREL radio link.
112      *
113      */
114     void Disable(void);
115 
116     /**
117      * This method requests TREL radio link to transition to Sleep mode
118      *
119      */
120     void Sleep(void);
121 
122     /**
123      * This method requests TREL radio link to transition to Receive mode on a given channel.
124      *
125      * `Mac::HandleReceivedFrame()` is used to notify MAC layer upon receiving a frame.
126      *
127      * @param[in] aChannel   The channel to receive on.
128      *
129      */
130     void Receive(uint8_t aChannel);
131 
132     /**
133      * This method gets the radio transmit frame for TREL radio link.
134      *
135      * @returns The transmit frame.
136      *
137      */
GetTransmitFrame(void)138     Mac::TxFrame &GetTransmitFrame(void) { return mTxFrame; }
139 
140     /**
141      * This method requests a frame to be sent over TREL radio link.
142      *
143      * The frame should be already placed in `GetTransmitFrame()` frame.
144      *
145      * `Mac::RecordFrameTransmitStatus()` and `Mac::HandleTransmitDone()` are used to notify the success or error status
146      * of frame transmission upon completion of send.
147      *
148      */
149     void Send(void);
150 
151 private:
152     static constexpr uint16_t kMaxHeaderSize   = sizeof(Header);
153     static constexpr uint16_t k154AckFrameSize = 3 + kFcsSize;
154     static constexpr int8_t   kRxRssi          = -20; // The RSSI value used for received frames on TREL radio link.
155     static constexpr uint32_t kAckWaitWindow   = 750; // (in msec)
156     static constexpr uint16_t kFcfFramePending = 1 << 4;
157 
158     enum State : uint8_t
159     {
160         kStateDisabled,
161         kStateSleep,
162         kStateReceive,
163         kStateTransmit,
164     };
165 
166     void AfterInit(void);
167     void SetState(State aState);
168     void BeginTransmit(void);
InvokeSendDone(Error aError)169     void InvokeSendDone(Error aError) { InvokeSendDone(aError, nullptr); }
170     void InvokeSendDone(Error aError, Mac::RxFrame *aAckFrame);
171     void ProcessReceivedPacket(Packet &aPacket);
172     void HandleAck(Packet &aAckPacket);
173     void SendAck(Packet &aRxPacket);
174     void ReportDeferredAckStatus(Neighbor &aNeighbor, Error aError);
175     void HandleTimer(Neighbor &aNeighbor);
176     void HandleNotifierEvents(Events aEvents);
177     void HandleTxTasklet(void);
178     void HandleTimer(void);
179 
180     static const char *StateToString(State aState);
181 
182     using TxTasklet    = TaskletIn<Link, &Link::HandleTxTasklet>;
183     using TimeoutTimer = TimerMilliIn<Link, &Link::HandleTimer>;
184 
185     State        mState;
186     uint8_t      mRxChannel;
187     Mac::PanId   mPanId;
188     uint32_t     mTxPacketNumber;
189     TxTasklet    mTxTasklet;
190     TimeoutTimer mTimer;
191     Interface    mInterface;
192     Mac::RxFrame mRxFrame;
193     Mac::TxFrame mTxFrame;
194     uint8_t      mTxPacketBuffer[kMaxHeaderSize + kMtuSize];
195     uint8_t      mAckPacketBuffer[kMaxHeaderSize];
196     uint8_t      mAckFrameBuffer[k154AckFrameSize];
197 };
198 
199 /**
200  * This class defines all the neighbor info required for TREL link.
201  *
202  * `Neighbor` class publicly inherits from this class.
203  *
204  */
205 class NeighborInfo
206 {
207     friend class Link;
208 
209 private:
GetPendingTrelAckCount(void) const210     uint32_t GetPendingTrelAckCount(void) const { return (mTrelPreviousPendingAcks + mTrelCurrentPendingAcks); }
211 
DecrementPendingTrelAckCount(void)212     void DecrementPendingTrelAckCount(void)
213     {
214         if (mTrelPreviousPendingAcks != 0)
215         {
216             mTrelPreviousPendingAcks--;
217         }
218         else if (mTrelCurrentPendingAcks != 0)
219         {
220             mTrelCurrentPendingAcks--;
221         }
222     }
223 
GetExpectedTrelAckNumber(void) const224     uint32_t GetExpectedTrelAckNumber(void) const { return mTrelTxPacketNumber - GetPendingTrelAckCount(); }
225 
IsRxAckNumberValid(uint32_t aAckNumber) const226     bool IsRxAckNumberValid(uint32_t aAckNumber) const
227     {
228         // Note that calculating the difference between `aAckNumber`
229         // and `GetExpectedTrelAckNumber` will correctly handle the
230         // roll-over of packet number value.
231 
232         return (GetPendingTrelAckCount() != 0) && (aAckNumber - GetExpectedTrelAckNumber() < GetPendingTrelAckCount());
233     }
234 
235     uint32_t mTrelTxPacketNumber;      // Next packet number to use for tx
236     uint16_t mTrelCurrentPendingAcks;  // Number of pending acks for current interval.
237     uint16_t mTrelPreviousPendingAcks; // Number of pending acks for previous interval.
238 };
239 
240 /**
241  * @}
242  *
243  */
244 
245 } // namespace Trel
246 } // namespace ot
247 
248 #endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
249 
250 #endif // TREL_LINK_HPP_
251