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 * Represents a Thread Radio Encapsulation Link (TREL). 68 */ 69 class Link : public InstanceLocator 70 { 71 friend class ot::Instance; 72 friend class ot::Notifier; 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 * Used as input by `CheckPeerAddrOnRxSuccess()` to determine whether the peer socket address can be updated based 81 * on a received TREL packet from the peer if there is a discrepancy. 82 */ 83 enum PeerSockAddrUpdateMode : uint8_t 84 { 85 kAllowPeerSockAddrUpdate, ///< Peer socket address can be updated. 86 kDisallowPeerSockAddrUpdate, ///< Peer socket address cannot be updated. 87 }; 88 89 /** 90 * Initializes the `Link` object. 91 * 92 * @param[in] aInstance A reference to the OpenThread instance. 93 */ 94 explicit Link(Instance &aInstance); 95 96 /** 97 * Sets the PAN Identifier. 98 * 99 * @param[in] aPanId A PAN Identifier. 100 */ SetPanId(Mac::PanId aPanId)101 void SetPanId(Mac::PanId aPanId) { mPanId = aPanId; } 102 103 /** 104 * Notifies TREL radio link that device's extended MAC address has changed for it to update any 105 * internal address/state. 106 */ HandleExtAddressChange(void)107 void HandleExtAddressChange(void) { mInterface.HandleExtAddressChange(); } 108 109 /** 110 * Enables the TREL radio link. 111 */ 112 void Enable(void); 113 114 /** 115 * Disables the TREL radio link. 116 */ 117 void Disable(void); 118 119 /** 120 * Requests TREL radio link to transition to Sleep mode 121 */ 122 void Sleep(void); 123 124 /** 125 * Requests TREL radio link to transition to Receive mode on a given channel. 126 * 127 * `Mac::HandleReceivedFrame()` is used to notify MAC layer upon receiving a frame. 128 * 129 * @param[in] aChannel The channel to receive on. 130 */ 131 void Receive(uint8_t aChannel); 132 133 /** 134 * Gets the radio transmit frame for TREL radio link. 135 * 136 * @returns The transmit frame. 137 */ GetTransmitFrame(void)138 Mac::TxFrame &GetTransmitFrame(void) { return mTxFrame; } 139 140 /** 141 * 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 void Send(void); 149 150 /** 151 * Checks the address/port from the last received TREL packet against the ones recorded in the corresponding `Peer` 152 * entry and acts if there is a discrepancy. 153 * 154 * This method signals to the platform about the discrepancy. Based on @p aMode, it may also update the `Peer` 155 * entry information directly to match the new address/port information. 156 * 157 * @param[in] aMode Determines whether to update the `Peer` entry if there is a discrepancy. 158 */ 159 void CheckPeerAddrOnRxSuccess(PeerSockAddrUpdateMode aMode); 160 161 private: 162 static constexpr uint16_t kMaxHeaderSize = sizeof(Header); 163 static constexpr uint16_t k154AckFrameSize = 3 + kFcsSize; 164 static constexpr int8_t kRxRssi = -20; // The RSSI value used for received frames on TREL radio link. 165 static constexpr uint32_t kAckWaitWindow = 750; // (in msec) 166 static constexpr uint16_t kFcfFramePending = 1 << 4; 167 168 typedef Interface::Peer Peer; 169 170 enum State : uint8_t 171 { 172 kStateDisabled, 173 kStateSleep, 174 kStateReceive, 175 kStateTransmit, 176 }; 177 178 void AfterInit(void); 179 void SetState(State aState); 180 void BeginTransmit(void); InvokeSendDone(Error aError)181 void InvokeSendDone(Error aError) { InvokeSendDone(aError, nullptr); } 182 void InvokeSendDone(Error aError, Mac::RxFrame *aAckFrame); 183 void ProcessReceivedPacket(Packet &aPacket, const Ip6::SockAddr &aSockAddr); 184 void HandleAck(Packet &aAckPacket); 185 void SendAck(Packet &aRxPacket); 186 void ReportDeferredAckStatus(Neighbor &aNeighbor, Error aError); 187 void HandleTimer(Neighbor &aNeighbor); 188 void HandleNotifierEvents(Events aEvents); 189 void HandleTxTasklet(void); 190 void HandleTimer(void); 191 192 static const char *StateToString(State aState); 193 194 using TxTasklet = TaskletIn<Link, &Link::HandleTxTasklet>; 195 using TimeoutTimer = TimerMilliIn<Link, &Link::HandleTimer>; 196 197 State mState; 198 uint8_t mRxChannel; 199 Mac::PanId mPanId; 200 uint32_t mTxPacketNumber; 201 TxTasklet mTxTasklet; 202 TimeoutTimer mTimer; 203 Interface mInterface; 204 Ip6::SockAddr mRxPacketSenderAddr; 205 Peer *mRxPacketPeer; 206 Mac::RxFrame mRxFrame; 207 Mac::TxFrame mTxFrame; 208 uint8_t mTxPacketBuffer[kMaxHeaderSize + kMtuSize]; 209 uint8_t mAckPacketBuffer[kMaxHeaderSize]; 210 uint8_t mAckFrameBuffer[k154AckFrameSize]; 211 }; 212 213 /** 214 * Defines all the neighbor info required for TREL link. 215 * 216 * `Neighbor` class publicly inherits from this class. 217 */ 218 class NeighborInfo 219 { 220 friend class Link; 221 222 private: GetPendingTrelAckCount(void) const223 uint32_t GetPendingTrelAckCount(void) const { return (mTrelPreviousPendingAcks + mTrelCurrentPendingAcks); } 224 DecrementPendingTrelAckCount(void)225 void DecrementPendingTrelAckCount(void) 226 { 227 if (mTrelPreviousPendingAcks != 0) 228 { 229 mTrelPreviousPendingAcks--; 230 } 231 else if (mTrelCurrentPendingAcks != 0) 232 { 233 mTrelCurrentPendingAcks--; 234 } 235 } 236 GetExpectedTrelAckNumber(void) const237 uint32_t GetExpectedTrelAckNumber(void) const { return mTrelTxPacketNumber - GetPendingTrelAckCount(); } 238 IsRxAckNumberValid(uint32_t aAckNumber) const239 bool IsRxAckNumberValid(uint32_t aAckNumber) const 240 { 241 // Note that calculating the difference between `aAckNumber` 242 // and `GetExpectedTrelAckNumber` will correctly handle the 243 // roll-over of packet number value. 244 245 return (GetPendingTrelAckCount() != 0) && (aAckNumber - GetExpectedTrelAckNumber() < GetPendingTrelAckCount()); 246 } 247 248 uint32_t mTrelTxPacketNumber; // Next packet number to use for tx 249 uint16_t mTrelCurrentPendingAcks; // Number of pending acks for current interval. 250 uint16_t mTrelPreviousPendingAcks; // Number of pending acks for previous interval. 251 }; 252 253 /** 254 * @} 255 */ 256 257 } // namespace Trel 258 } // namespace ot 259 260 #endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE 261 262 #endif // TREL_LINK_HPP_ 263