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