1 /* 2 * Copyright (c) 2016, 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 forwarding IPv6 datagrams across the Thread mesh. 32 */ 33 34 #ifndef MESH_FORWARDER_HPP_ 35 #define MESH_FORWARDER_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/clearable.hpp" 40 #include "common/locator.hpp" 41 #include "common/non_copyable.hpp" 42 #include "common/tasklet.hpp" 43 #include "common/time_ticker.hpp" 44 #include "mac/channel_mask.hpp" 45 #include "mac/data_poll_sender.hpp" 46 #include "mac/mac.hpp" 47 #include "mac/mac_frame.hpp" 48 #include "net/ip6.hpp" 49 #include "thread/address_resolver.hpp" 50 #include "thread/indirect_sender.hpp" 51 #include "thread/lowpan.hpp" 52 #include "thread/network_data_leader.hpp" 53 #include "thread/topology.hpp" 54 55 namespace ot { 56 57 namespace Mle { 58 class DiscoverScanner; 59 } 60 61 namespace Utils { 62 class HistoryTracker; 63 } 64 65 /** 66 * @addtogroup core-mesh-forwarding 67 * 68 * @brief 69 * This module includes definitions for mesh forwarding within Thread. 70 * 71 * @{ 72 */ 73 74 /** 75 * This class represents link-specific information for messages received from the Thread radio. 76 * 77 */ 78 class ThreadLinkInfo : public otThreadLinkInfo, public Clearable<ThreadLinkInfo> 79 { 80 public: 81 /** 82 * This method returns the IEEE 802.15.4 Source PAN ID. 83 * 84 * @returns The IEEE 802.15.4 Source PAN ID. 85 * 86 */ GetPanId(void) const87 Mac::PanId GetPanId(void) const { return mPanId; } 88 89 /** 90 * This method returns the IEEE 802.15.4 Channel. 91 * 92 * @returns The IEEE 802.15.4 Channel. 93 * 94 */ GetChannel(void) const95 uint8_t GetChannel(void) const { return mChannel; } 96 97 /** 98 * This method indicates whether or not link security is enabled. 99 * 100 * @retval TRUE If link security is enabled. 101 * @retval FALSE If link security is not enabled. 102 * 103 */ IsLinkSecurityEnabled(void) const104 bool IsLinkSecurityEnabled(void) const { return mLinkSecurity; } 105 106 /** 107 * This method returns the Received Signal Strength (RSS) in dBm. 108 * 109 * @returns The Received Signal Strength (RSS) in dBm. 110 * 111 */ GetRss(void) const112 int8_t GetRss(void) const { return mRss; } 113 114 /** 115 * This method returns the frame/radio Link Quality Indicator (LQI) value. 116 * 117 * @returns The Link Quality Indicator value. 118 * 119 */ GetLqi(void) const120 uint8_t GetLqi(void) const { return mLqi; } 121 122 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 123 /** 124 * This method returns the Time Sync Sequence. 125 * 126 * @returns The Time Sync Sequence. 127 * 128 */ GetTimeSyncSeq(void) const129 uint8_t GetTimeSyncSeq(void) const { return mTimeSyncSeq; } 130 131 /** 132 * This method returns the time offset to the Thread network time (in microseconds). 133 * 134 * @returns The time offset to the Thread network time (in microseconds). 135 * 136 */ GetNetworkTimeOffset(void) const137 int64_t GetNetworkTimeOffset(void) const { return mNetworkTimeOffset; } 138 #endif 139 140 /** 141 * This method sets the `ThreadLinkInfo` from a given received frame. 142 * 143 * @param[in] aFrame A received frame. 144 * 145 */ 146 void SetFrom(const Mac::RxFrame &aFrame); 147 }; 148 149 /** 150 * This class implements mesh forwarding within Thread. 151 * 152 */ 153 class MeshForwarder : public InstanceLocator, private NonCopyable 154 { 155 friend class Mac::Mac; 156 friend class Instance; 157 friend class DataPollSender; 158 friend class IndirectSender; 159 friend class Mle::DiscoverScanner; 160 friend class TimeTicker; 161 friend class Utils::HistoryTracker; 162 163 public: 164 /** 165 * This constructor initializes the object. 166 * 167 * @param[in] aInstance A reference to the OpenThread instance. 168 * 169 */ 170 explicit MeshForwarder(Instance &aInstance); 171 172 /** 173 * This method enables mesh forwarding and the IEEE 802.15.4 MAC layer. 174 * 175 */ 176 void Start(void); 177 178 /** 179 * This method disables mesh forwarding and the IEEE 802.15.4 MAC layer. 180 * 181 */ 182 void Stop(void); 183 184 /** 185 * This method submits a message to the mesh forwarder for forwarding. 186 * 187 * @param[in] aMessage A reference to the message. 188 * 189 * @retval kErrorNone Successfully enqueued the message. 190 * @retval kErrorAlready The message was already enqueued. 191 * @retval kErrorDrop The message could not be sent and should be dropped. 192 * 193 */ 194 Error SendMessage(Message &aMessage); 195 196 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 197 /** 198 * This method sends an empty data frame to the parent. 199 * 200 * @retval kErrorNone Successfully enqueued an empty message. 201 * @retval kErrorInvalidState Device is not in Rx-Off-When-Idle mode or it has no parent. 202 * @retval kErrorNoBufs Insufficient message buffers available. 203 * 204 */ 205 Error SendEmptyMessage(void); 206 #endif 207 208 /** 209 * This method is called by the address resolver when an EID-to-RLOC mapping has been resolved. 210 * 211 * @param[in] aEid A reference to the EID that has been resolved. 212 * @param[in] aError kErrorNone on success and kErrorDrop otherwise. 213 * 214 */ 215 void HandleResolved(const Ip6::Address &aEid, Error aError); 216 217 /** 218 * This method indicates whether or not rx-on-when-idle mode is enabled. 219 * 220 * @retval TRUE The rx-on-when-idle mode is enabled. 221 * @retval FALSE The rx-on-when-idle-mode is disabled. 222 * 223 */ 224 bool GetRxOnWhenIdle(void) const; 225 226 /** 227 * This method sets the rx-on-when-idle mode 228 * 229 * @param[in] aRxOnWhenIdle TRUE to enable, FALSE otherwise. 230 * 231 */ 232 void SetRxOnWhenIdle(bool aRxOnWhenIdle); 233 234 /** 235 * This method sets the scan parameters for MLE Discovery Request messages. 236 * 237 * @param[in] aScanChannels A reference to channel mask indicating which channels to scan. 238 * If @p aScanChannels is empty, then all channels are used instead. 239 * 240 */ 241 void SetDiscoverParameters(const Mac::ChannelMask &aScanChannels); 242 243 #if OPENTHREAD_FTD 244 /** 245 * This method frees any messages queued for an existing child. 246 * 247 * @param[in] aChild A reference to the child. 248 * @param[in] aSubType The message sub-type to remove. 249 * Use Message::kSubTypeNone remove all messages for @p aChild. 250 * 251 */ 252 void RemoveMessages(Child &aChild, Message::SubType aSubType); 253 #endif 254 255 /** 256 * This method frees unicast/multicast MLE Data Responses from Send Message Queue if any. 257 * 258 */ 259 void RemoveDataResponseMessages(void); 260 261 /** 262 * This method evicts the message with lowest priority in the send queue. 263 * 264 * @param[in] aPriority The highest priority level of the evicted message. 265 * 266 * @retval kErrorNone Successfully evicted a low priority message. 267 * @retval kErrorNotFound No low priority messages available to evict. 268 * 269 */ 270 Error EvictMessage(Message::Priority aPriority); 271 272 /** 273 * This method returns a reference to the send queue. 274 * 275 * @returns A reference to the send queue. 276 * 277 */ GetSendQueue(void) const278 const PriorityQueue &GetSendQueue(void) const { return mSendQueue; } 279 280 /** 281 * This method returns a reference to the reassembly queue. 282 * 283 * @returns A reference to the reassembly queue. 284 * 285 */ GetReassemblyQueue(void) const286 const MessageQueue &GetReassemblyQueue(void) const { return mReassemblyList; } 287 288 /** 289 * This method returns a reference to the IP level counters. 290 * 291 * @returns A reference to the IP level counters. 292 * 293 */ GetCounters(void) const294 const otIpCounters &GetCounters(void) const { return mIpCounters; } 295 296 /** 297 * This method resets the IP level counters. 298 * 299 */ ResetCounters(void)300 void ResetCounters(void) { memset(&mIpCounters, 0, sizeof(mIpCounters)); } 301 302 #if OPENTHREAD_FTD 303 /** 304 * This method returns a reference to the resolving queue. 305 * 306 * @returns A reference to the resolving queue. 307 * 308 */ GetResolvingQueue(void) const309 const PriorityQueue &GetResolvingQueue(void) const { return mResolvingQueue; } 310 #endif 311 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE 312 /** 313 * This method handles a deferred ack. 314 * 315 * Some radio links can use deferred ack logic, where a tx request always report `HandleSentFrame()` quickly. The 316 * link layer would wait for the ack and report it at a later time using this method. 317 * 318 * The link layer is expected to call `HandleDeferredAck()` (with success or failure status) for every tx request 319 * on the radio link. 320 * 321 * @param[in] aNeighbor The neighbor for which the deferred ack status is being reported. 322 * @param[in] aError The deferred ack error status: `kErrorNone` to indicate a deferred ack was received, 323 * `kErrorNoAck` to indicate an ack timeout. 324 * 325 */ 326 void HandleDeferredAck(Neighbor &aNeighbor, Error aError); 327 #endif 328 329 private: 330 static constexpr uint8_t kReassemblyTimeout = OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT; // in seconds. 331 static constexpr uint8_t kMeshHeaderFrameMtu = OT_RADIO_FRAME_MAX_SIZE; // Max MTU with a Mesh Header frame. 332 static constexpr uint8_t kMeshHeaderFrameFcsSize = sizeof(uint16_t); // Frame FCS size for Mesh Header frame. 333 334 enum MessageAction : uint8_t 335 { 336 kMessageReceive, // Indicates that the message was received. 337 kMessageTransmit, // Indicates that the message was sent. 338 kMessagePrepareIndirect, // Indicates that the message is being prepared for indirect tx. 339 kMessageDrop, // Indicates that the outbound message is being dropped (e.g., dst unknown). 340 kMessageReassemblyDrop, // Indicates that the message is being dropped from reassembly list. 341 kMessageEvict, // Indicates that the message was evicted. 342 }; 343 344 enum AnycastType : uint8_t 345 { 346 kAnycastDhcp6Agent, 347 kAnycastNeighborDiscoveryAgent, 348 kAnycastService, 349 }; 350 351 #if OPENTHREAD_FTD 352 class FragmentPriorityList : public Clearable<FragmentPriorityList> 353 { 354 public: 355 class Entry : public Clearable<Entry> 356 { 357 friend class FragmentPriorityList; 358 359 public: GetPriority(void) const360 Message::Priority GetPriority(void) const { return mPriority; } IsExpired(void) const361 bool IsExpired(void) const { return (mLifetime == 0); } DecrementLifetime(void)362 void DecrementLifetime(void) { mLifetime--; } ResetLifetime(void)363 void ResetLifetime(void) { mLifetime = kReassemblyTimeout; } 364 Matches(uint16_t aSrcRloc16,uint16_t aTag) const365 bool Matches(uint16_t aSrcRloc16, uint16_t aTag) const 366 { 367 return (mSrcRloc16 == aSrcRloc16) && (mDatagramTag == aTag); 368 } 369 370 private: 371 uint16_t mSrcRloc16; 372 uint16_t mDatagramTag; 373 Message::Priority mPriority; 374 uint8_t mLifetime; 375 }; 376 377 Entry *AllocateEntry(uint16_t aSrcRloc16, uint16_t aTag, Message::Priority aPriority); 378 Entry *FindEntry(uint16_t aSrcRloc16, uint16_t aTag); 379 bool UpdateOnTimeTick(void); 380 381 private: 382 static constexpr uint16_t kNumEntries = OPENTHREAD_CONFIG_NUM_FRAGMENT_PRIORITY_ENTRIES; 383 384 Entry mEntries[kNumEntries]; 385 }; 386 #endif // OPENTHREAD_FTD 387 388 void SendIcmpErrorIfDstUnreach(const Message & aMessage, 389 const Mac::Address &aMacSource, 390 const Mac::Address &aMacDest); 391 Error CheckReachability(const uint8_t * aFrame, 392 uint16_t aFrameLength, 393 const Mac::Address &aMeshSource, 394 const Mac::Address &aMeshDest); 395 void UpdateRoutes(const uint8_t * aFrame, 396 uint16_t aFrameLength, 397 const Mac::Address &aMeshSource, 398 const Mac::Address &aMeshDest); 399 400 Error DecompressIp6Header(const uint8_t * aFrame, 401 uint16_t aFrameLength, 402 const Mac::Address &aMacSource, 403 const Mac::Address &aMacDest, 404 Ip6::Header & aIp6Header, 405 uint8_t & aHeaderLength, 406 bool & aNextHeaderCompressed); 407 Error FrameToMessage(const uint8_t * aFrame, 408 uint16_t aFrameLength, 409 uint16_t aDatagramSize, 410 const Mac::Address &aMacSource, 411 const Mac::Address &aMacDest, 412 Message *& aMessage); 413 Error GetIp6Header(const uint8_t * aFrame, 414 uint16_t aFrameLength, 415 const Mac::Address &aMacSource, 416 const Mac::Address &aMacDest, 417 Ip6::Header & aIp6Header); 418 void GetMacDestinationAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr); 419 void GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr); 420 Message *GetDirectTransmission(void); 421 void HandleMesh(uint8_t * aFrame, 422 uint16_t aFrameLength, 423 const Mac::Address & aMacSource, 424 const ThreadLinkInfo &aLinkInfo); 425 void HandleFragment(const uint8_t * aFrame, 426 uint16_t aFrameLength, 427 const Mac::Address & aMacSource, 428 const Mac::Address & aMacDest, 429 const ThreadLinkInfo &aLinkInfo); 430 void HandleLowpanHC(const uint8_t * aFrame, 431 uint16_t aFrameLength, 432 const Mac::Address & aMacSource, 433 const Mac::Address & aMacDest, 434 const ThreadLinkInfo &aLinkInfo); 435 uint16_t PrepareDataFrame(Mac::TxFrame & aFrame, 436 Message & aMessage, 437 const Mac::Address &aMacSource, 438 const Mac::Address &aMacDest, 439 bool aAddMeshHeader = false, 440 uint16_t aMeshSource = 0xffff, 441 uint16_t aMeshDest = 0xffff, 442 bool aAddFragHeader = false); 443 void PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &aMacDest, bool aAckRequest); 444 445 void SendMesh(Message &aMessage, Mac::TxFrame &aFrame); 446 void SendDestinationUnreachable(uint16_t aMeshSource, const Message &aMessage); 447 Error UpdateIp6Route(Message &aMessage); 448 Error UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessage); 449 void EvaluateRoutingCost(uint16_t aDest, uint8_t &aBestCost, uint16_t &aBestDest) const; 450 Error AnycastRouteLookup(uint8_t aServiceId, AnycastType aType, uint16_t &aMeshDest) const; 451 Error UpdateMeshRoute(Message &aMessage); 452 bool UpdateReassemblyList(void); 453 void UpdateFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader, 454 uint16_t aFragmentLength, 455 uint16_t aSrcRloc16, 456 Message::Priority aPriority); 457 Error HandleDatagram(Message &aMessage, const ThreadLinkInfo &aLinkInfo, const Mac::Address &aMacSource); 458 void ClearReassemblyList(void); 459 void RemoveMessage(Message &aMessage); 460 void HandleDiscoverComplete(void); 461 462 void HandleReceivedFrame(Mac::RxFrame &aFrame); 463 Mac::TxFrame *HandleFrameRequest(Mac::TxFrames &aTxFrames); 464 Neighbor * UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, Error aError, const Mac::Address &aMacDest); 465 void UpdateNeighborLinkFailures(Neighbor &aNeighbor, 466 Error aError, 467 bool aAllowNeighborRemove, 468 uint8_t aFailLimit = Mle::kFailedRouterTransmissions); 469 void HandleSentFrame(Mac::TxFrame &aFrame, Error aError); 470 void UpdateSendMessage(Error aFrameTxError, Mac::Address &aMacDest, Neighbor *aNeighbor); 471 void RemoveMessageIfNoPendingTx(Message &aMessage); 472 473 void HandleTimeTick(void); 474 static void ScheduleTransmissionTask(Tasklet &aTasklet); 475 void ScheduleTransmissionTask(void); 476 477 Error GetFramePriority(const uint8_t * aFrame, 478 uint16_t aFrameLength, 479 const Mac::Address &aMacSource, 480 const Mac::Address &aMacDest, 481 Message::Priority & aPriority); 482 Error GetFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader, 483 uint16_t aSrcRloc16, 484 Message::Priority & aPriority); 485 void GetForwardFramePriority(const uint8_t * aFrame, 486 uint16_t aFrameLength, 487 const Mac::Address &aMeshSource, 488 const Mac::Address &aMeshDest, 489 Message::Priority & aPriority); 490 491 bool CalcIePresent(const Message *aMessage); 492 uint16_t CalcFrameVersion(const Neighbor *aNeighbor, bool aIePresent); 493 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 494 void AppendHeaderIe(const Message *aMessage, Mac::TxFrame &aFrame); 495 #endif 496 PauseMessageTransmissions(void)497 void PauseMessageTransmissions(void) { mTxPaused = true; } 498 void ResumeMessageTransmissions(void); 499 500 void LogMessage(MessageAction aAction, const Message &aMessage, const Mac::Address *aAddress, Error aError); 501 void LogFrame(const char *aActionText, const Mac::Frame &aFrame, Error aError); 502 void LogFragmentFrameDrop(Error aError, 503 uint16_t aFrameLength, 504 const Mac::Address & aMacSource, 505 const Mac::Address & aMacDest, 506 const Lowpan::FragmentHeader &aFragmentHeader, 507 bool aIsSecure); 508 void LogLowpanHcFrameDrop(Error aError, 509 uint16_t aFrameLength, 510 const Mac::Address &aMacSource, 511 const Mac::Address &aMacDest, 512 bool aIsSecure); 513 514 static Error ParseIp6UdpTcpHeader(const Message &aMessage, 515 Ip6::Header & aIp6Header, 516 uint16_t & aChecksum, 517 uint16_t & aSourcePort, 518 uint16_t & aDestPort); 519 520 #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1) 521 const char *MessageActionToString(MessageAction aAction, Error aError); 522 const char *MessagePriorityToString(const Message &aMessage); 523 524 #if OPENTHREAD_FTD 525 Error DecompressIp6UdpTcpHeader(const Message & aMessage, 526 uint16_t aOffset, 527 const Mac::Address &aMeshSource, 528 const Mac::Address &aMeshDest, 529 Ip6::Header & aIp6Header, 530 uint16_t & aChecksum, 531 uint16_t & aSourcePort, 532 uint16_t & aDestPort); 533 Error LogMeshFragmentHeader(MessageAction aAction, 534 const Message & aMessage, 535 const Mac::Address *aMacAddress, 536 Error aError, 537 uint16_t & aOffset, 538 Mac::Address & aMeshSource, 539 Mac::Address & aMeshDest, 540 otLogLevel aLogLevel); 541 void LogMeshIpHeader(const Message & aMessage, 542 uint16_t aOffset, 543 const Mac::Address &aMeshSource, 544 const Mac::Address &aMeshDest, 545 otLogLevel aLogLevel); 546 void LogMeshMessage(MessageAction aAction, 547 const Message & aMessage, 548 const Mac::Address *aAddress, 549 Error aError, 550 otLogLevel aLogLevel); 551 #endif 552 void LogIp6SourceDestAddresses(Ip6::Header &aIp6Header, 553 uint16_t aSourcePort, 554 uint16_t aDestPort, 555 otLogLevel aLogLevel); 556 void LogIp6Message(MessageAction aAction, 557 const Message & aMessage, 558 const Mac::Address *aAddress, 559 Error aError, 560 otLogLevel aLogLevel); 561 #endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1) 562 563 PriorityQueue mSendQueue; 564 MessageQueue mReassemblyList; 565 uint16_t mFragTag; 566 uint16_t mMessageNextOffset; 567 568 Message *mSendMessage; 569 570 Mac::Address mMacSource; 571 Mac::Address mMacDest; 572 uint16_t mMeshSource; 573 uint16_t mMeshDest; 574 bool mAddMeshHeader : 1; 575 bool mEnabled : 1; 576 bool mTxPaused : 1; 577 bool mSendBusy : 1; 578 579 Tasklet mScheduleTransmissionTask; 580 581 otIpCounters mIpCounters; 582 583 #if OPENTHREAD_FTD 584 FragmentPriorityList mFragmentPriorityList; 585 PriorityQueue mResolvingQueue; 586 IndirectSender mIndirectSender; 587 #endif 588 589 DataPollSender mDataPollSender; 590 }; 591 592 /** 593 * @} 594 * 595 */ 596 597 } // namespace ot 598 599 #endif // MESH_FORWARDER_HPP_ 600