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 6LoWPAN header compression. 32 */ 33 34 #ifndef LOWPAN_HPP_ 35 #define LOWPAN_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/clearable.hpp" 40 #include "common/debug.hpp" 41 #include "common/frame_builder.hpp" 42 #include "common/frame_data.hpp" 43 #include "common/locator.hpp" 44 #include "common/message.hpp" 45 #include "common/non_copyable.hpp" 46 #include "mac/mac_types.hpp" 47 #include "net/ip6.hpp" 48 #include "net/ip6_address.hpp" 49 #include "net/ip6_types.hpp" 50 51 namespace ot { 52 53 /** 54 * @addtogroup core-6lowpan 55 * 56 * @brief 57 * This module includes definitions for 6LoWPAN header compression. 58 * 59 * @{ 60 */ 61 62 /** 63 * @namespace ot::Lowpan 64 * 65 * @brief 66 * This namespace includes definitions for 6LoWPAN message processing. 67 */ 68 namespace Lowpan { 69 70 /** 71 * Represents a LOWPAN_IPHC Context. 72 */ 73 struct Context : public Clearable<Context> 74 { 75 Ip6::Prefix mPrefix; ///< The Prefix 76 uint8_t mContextId; ///< The Context ID. 77 bool mCompressFlag; ///< The Context compression flag. 78 bool mIsValid; ///< Indicates whether the context is valid. 79 }; 80 81 /** 82 * Implements LOWPAN_IPHC header compression. 83 */ 84 class Lowpan : public InstanceLocator, private NonCopyable 85 { 86 public: 87 /** 88 * Initializes the object. 89 * 90 * @param[in] aInstance A reference to the OpenThread instance. 91 */ 92 explicit Lowpan(Instance &aInstance); 93 94 /** 95 * Indicates whether or not the header is a LOWPAN_IPHC header. 96 * 97 * @param[in] aHeader A pointer to the header. 98 * 99 * @retval TRUE If the header matches the LOWPAN_IPHC dispatch value. 100 * @retval FALSE If the header does not match the LOWPAN_IPHC dispatch value. 101 */ IsLowpanHc(const uint8_t * aHeader)102 static bool IsLowpanHc(const uint8_t *aHeader) 103 { 104 return (aHeader[0] & (Lowpan::kHcDispatchMask >> 8)) == (Lowpan::kHcDispatch >> 8); 105 } 106 107 /** 108 * Indicates whether or not header in a given frame is a LOWPAN_IPHC header. 109 * 110 * @param[in] aFrameData The frame data. 111 * 112 * @retval TRUE If the header matches the LOWPAN_IPHC dispatch value. 113 * @retval FALSE If the header does not match the LOWPAN_IPHC dispatch value. 114 */ IsLowpanHc(const FrameData & aFrameData)115 static bool IsLowpanHc(const FrameData &aFrameData) 116 { 117 return (aFrameData.GetLength() > 0) && IsLowpanHc(aFrameData.GetBytes()); 118 } 119 120 /** 121 * Compresses an IPv6 header. 122 * 123 * @param[in] aMessage A reference to the IPv6 message. 124 * @param[in] aMacAddrs The MAC source and destination addresses. 125 * @param[in] aFrameBuilder The `FrameBuilder` to use to append the compressed headers. 126 * 127 * @returns The size of the compressed header in bytes. 128 */ 129 Error Compress(Message &aMessage, const Mac::Addresses &aMacAddrs, FrameBuilder &aFrameBuilder); 130 131 /** 132 * Decompresses a LOWPAN_IPHC header. 133 * 134 * If the header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes. 135 * 136 * @param[out] aMessage A reference where the IPv6 header will be placed. 137 * @param[in] aMacAddrs The MAC source and destination addresses. 138 * @param[in,out] aFrameData A frame data containing the LOWPAN_IPHC header. 139 * @param[in] aDatagramLength The IPv6 datagram length. 140 * 141 * @retval kErrorNone The header was decompressed successfully. @p aMessage and @p aFrameData are updated. 142 * @retval kErrorParse Failed to parse the lowpan header. 143 * @retval kErrorNoBufs Could not grow @p aMessage to write the parsed IPv6 header. 144 */ 145 Error Decompress(Message &aMessage, 146 const Mac::Addresses &aMacAddrs, 147 FrameData &aFrameData, 148 uint16_t aDatagramLength); 149 150 /** 151 * Decompresses a LOWPAN_IPHC header. 152 * 153 * If the header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes. 154 * 155 * @param[out] aIp6Header A reference where the IPv6 header will be placed. 156 * @param[out] aCompressedNextHeader A boolean reference to output whether next header is compressed or not. 157 * @param[in] aMacAddrs The MAC source and destination addresses 158 * @param[in,out] aFrameData A frame data containing the LOWPAN_IPHC header. 159 * 160 * @retval kErrorNone The header was decompressed successfully. @p aIp6Header and @p aFrameData are updated. 161 * @retval kErrorParse Failed to parse the lowpan header. 162 */ 163 Error DecompressBaseHeader(Ip6::Header &aIp6Header, 164 bool &aCompressedNextHeader, 165 const Mac::Addresses &aMacAddrs, 166 FrameData &aFrameData); 167 168 /** 169 * Decompresses a LOWPAN_NHC UDP header. 170 * 171 * If the header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes. 172 * 173 * @param[out] aUdpHeader A reference where the UDP header will be placed. 174 * @param[in,out] aFrameData A frame data containing the LOWPAN_NHC header. 175 * 176 * @retval kErrorNone The header was decompressed successfully. @p aUdpHeader and @p aFrameData are updated. 177 * @retval kErrorParse Failed to parse the lowpan header. 178 */ 179 Error DecompressUdpHeader(Ip6::Udp::Header &aUdpHeader, FrameData &aFrameData); 180 181 /** 182 * Decompresses the IPv6 ECN field in a LOWPAN_IPHC header. 183 * 184 * @param[in] aMessage The message to read the IPHC header from. 185 * @param[in] aOffset The offset in @p aMessage to start of IPHC header. 186 * 187 * @returns The decompressed ECN field. If the IPHC header is not valid `kEcnNotCapable` is returned. 188 */ 189 Ip6::Ecn DecompressEcn(const Message &aMessage, uint16_t aOffset) const; 190 191 /** 192 * Updates the compressed ECN field in a LOWPAN_IPHC header to `kEcnMarked`. 193 * 194 * MUST be used when the ECN field is not elided in the IPHC header. Note that the ECN is not elided 195 * when it is not zero (`kEcnNotCapable`). 196 * 197 * @param[in,out] aMessage The message containing the IPHC header and to update. 198 * @param[in] aOffset The offset in @p aMessage to start of IPHC header. 199 */ 200 void MarkCompressedEcn(Message &aMessage, uint16_t aOffset); 201 202 private: 203 static constexpr uint16_t kHcDispatch = 3 << 13; 204 static constexpr uint16_t kHcDispatchMask = 7 << 13; 205 206 static constexpr uint16_t kHcTrafficClass = 1 << 11; 207 static constexpr uint16_t kHcFlowLabel = 2 << 11; 208 static constexpr uint16_t kHcTrafficFlow = 3 << 11; 209 static constexpr uint16_t kHcTrafficFlowMask = 3 << 11; 210 static constexpr uint16_t kHcNextHeader = 1 << 10; 211 static constexpr uint16_t kHcHopLimit1 = 1 << 8; 212 static constexpr uint16_t kHcHopLimit64 = 2 << 8; 213 static constexpr uint16_t kHcHopLimit255 = 3 << 8; 214 static constexpr uint16_t kHcHopLimitMask = 3 << 8; 215 static constexpr uint16_t kHcContextId = 1 << 7; 216 static constexpr uint16_t kHcSrcAddrContext = 1 << 6; 217 static constexpr uint16_t kHcSrcAddrMode0 = 0 << 4; 218 static constexpr uint16_t kHcSrcAddrMode1 = 1 << 4; 219 static constexpr uint16_t kHcSrcAddrMode2 = 2 << 4; 220 static constexpr uint16_t kHcSrcAddrMode3 = 3 << 4; 221 static constexpr uint16_t kHcSrcAddrModeMask = 3 << 4; 222 static constexpr uint16_t kHcMulticast = 1 << 3; 223 static constexpr uint16_t kHcDstAddrContext = 1 << 2; 224 static constexpr uint16_t kHcDstAddrMode0 = 0 << 0; 225 static constexpr uint16_t kHcDstAddrMode1 = 1 << 0; 226 static constexpr uint16_t kHcDstAddrMode2 = 2 << 0; 227 static constexpr uint16_t kHcDstAddrMode3 = 3 << 0; 228 static constexpr uint16_t kHcDstAddrModeMask = 3 << 0; 229 230 static constexpr uint8_t kEcnOffset = 6; 231 static constexpr uint8_t kEcnMask = 3 << kEcnOffset; 232 233 static constexpr uint8_t kExtHdrDispatch = 0xe0; 234 static constexpr uint8_t kExtHdrDispatchMask = 0xf0; 235 236 static constexpr uint8_t kExtHdrEidHbh = 0x00; 237 static constexpr uint8_t kExtHdrEidRouting = 0x02; 238 static constexpr uint8_t kExtHdrEidFragment = 0x04; 239 static constexpr uint8_t kExtHdrEidDst = 0x06; 240 static constexpr uint8_t kExtHdrEidMobility = 0x08; 241 static constexpr uint8_t kExtHdrEidIp6 = 0x0e; 242 static constexpr uint8_t kExtHdrEidMask = 0x0e; 243 244 static constexpr uint8_t kExtHdrNextHeader = 0x01; 245 static constexpr uint16_t kExtHdrMaxLength = 255; 246 247 static constexpr uint8_t kUdpDispatch = 0xf0; 248 static constexpr uint8_t kUdpDispatchMask = 0xf8; 249 250 static constexpr uint8_t kUdpChecksum = 1 << 2; 251 static constexpr uint8_t kUdpPortMask = 3 << 0; 252 253 void FindContextForId(uint8_t aContextId, Context &aContext) const; 254 void FindContextToCompressAddress(const Ip6::Address &aIp6Address, Context &aContext) const; 255 Error Compress(Message &aMessage, 256 const Mac::Addresses &aMacAddrs, 257 FrameBuilder &aFrameBuilder, 258 uint8_t &aHeaderDepth); 259 260 Error CompressExtensionHeader(Message &aMessage, FrameBuilder &aFrameBuilder, uint8_t &aNextHeader); 261 Error CompressSourceIid(const Mac::Address &aMacAddr, 262 const Ip6::Address &aIpAddr, 263 const Context &aContext, 264 uint16_t &aHcCtl, 265 FrameBuilder &aFrameBuilder); 266 Error CompressDestinationIid(const Mac::Address &aMacAddr, 267 const Ip6::Address &aIpAddr, 268 const Context &aContext, 269 uint16_t &aHcCtl, 270 FrameBuilder &aFrameBuilder); 271 Error CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, FrameBuilder &aFrameBuilder); 272 Error CompressUdp(Message &aMessage, FrameBuilder &aFrameBuilder); 273 274 Error DecompressExtensionHeader(Message &aMessage, FrameData &aFrameData); 275 Error DecompressUdpHeader(Message &aMessage, FrameData &aFrameData, uint16_t aDatagramLength); 276 Error DispatchToNextHeader(uint8_t aDispatch, uint8_t &aNextHeader); 277 278 static Error ComputeIid(const Mac::Address &aMacAddr, const Context &aContext, Ip6::InterfaceIdentifier &aIid); 279 }; 280 281 /** 282 * Implements Mesh Header generation and processing. 283 */ 284 class MeshHeader 285 { 286 public: 287 /** 288 * Initializes the Mesh Header with a given Mesh Source, Mesh Destination and Hops Left value. 289 * 290 * @param[in] aSource The Mesh Source address. 291 * @param[in] aDestination The Mesh Destination address. 292 * @param[in] aHopsLeft The Hops Left value. 293 */ 294 void Init(uint16_t aSource, uint16_t aDestination, uint8_t aHopsLeft); 295 296 /** 297 * Indicates whether or not the header (in a given frame) is a Mesh Header. 298 * 299 * @note This method checks whether the first byte in header/frame (dispatch byte) matches the Mesh Header dispatch 300 * It does not fully parse and validate the Mesh Header. `ParseFrom()` method can be used to fully parse and 301 * validate the header. 302 * 303 * @retval TRUE If the header matches the Mesh Header dispatch value. 304 * @retval FALSE If the header does not match the Mesh Header dispatch value. 305 */ 306 static bool IsMeshHeader(const FrameData &aFrameData); 307 308 /** 309 * Parses the Mesh Header from a frame @p aFrame. 310 * 311 * @param[in] aFrame The pointer to the frame. 312 * @param[in] aFrameLength The length of the frame. 313 * @param[out] aHeaderLength A reference to a variable to output the parsed header length (on success). 314 * 315 * @retval kErrorNone Mesh Header parsed successfully. 316 * @retval kErrorParse Mesh Header could not be parsed. 317 */ 318 Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength); 319 320 /** 321 * Parses the Mesh Header from a given frame data. 322 * 323 * If the Mesh Header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes. 324 * 325 * @param[in,out] aFrameData The frame data to parse from. 326 * 327 * @retval kErrorNone Mesh Header parsed successfully. @p aFrameData is updated to skip over parsed header. 328 * @retval kErrorParse Mesh Header could not be parsed. 329 */ 330 Error ParseFrom(FrameData &aFrameData); 331 332 /** 333 * Parses the Mesh Header from a given message. 334 * 335 * @note The Mesh Header is read from offset zero within the @p aMessage. 336 * 337 * @param[in] aMessage The message to read from. 338 * 339 * @retval kErrorNone Mesh Header parsed successfully. 340 * @retval kErrorParse Mesh Header could not be parsed. 341 */ 342 Error ParseFrom(const Message &aMessage); 343 344 /** 345 * Parses the Mesh Header from a given message. 346 * 347 * @note The Mesh Header is read from offset zero within the @p aMessage. 348 * 349 * @param[in] aMessage The message to read from. 350 * @param[out] aHeaderLength A reference to a variable to output the parsed header length (on success). 351 * 352 * @retval kErrorNone Mesh Header parsed successfully. 353 * @retval kErrorParse Mesh Header could not be parsed. 354 */ 355 Error ParseFrom(const Message &aMessage, uint16_t &aHeaderLength); 356 357 /** 358 * Returns the the Mesh Header length when written to a frame. 359 * 360 * @note The returned value from this method gives the header length (number of bytes) when the header is written 361 * to a frame or message. This should not be used to determine the parsed length (number of bytes read) when the 362 * Mesh Header is parsed from a frame/message (using `ParseFrom()` methods). 363 * 364 * @returns The length of the Mesh Header (in bytes) when written to a frame. 365 */ 366 uint16_t GetHeaderLength(void) const; 367 368 /** 369 * Returns the Hops Left value. 370 * 371 * @returns The Hops Left value. 372 */ GetHopsLeft(void) const373 uint8_t GetHopsLeft(void) const { return mHopsLeft; } 374 375 /** 376 * Decrements the Hops Left value (if it is not zero). 377 */ 378 void DecrementHopsLeft(void); 379 380 /** 381 * Returns the Mesh Source address. 382 * 383 * @returns The Mesh Source address. 384 */ GetSource(void) const385 uint16_t GetSource(void) const { return mSource; } 386 387 /** 388 * Returns the Mesh Destination address. 389 * 390 * @returns The Mesh Destination address. 391 */ GetDestination(void) const392 uint16_t GetDestination(void) const { return mDestination; } 393 394 /** 395 * Appends the Mesh Header into a given frame. 396 * 397 * @param[out] aFrameBuilder The `FrameBuilder` to append to. 398 * 399 * @retval kErrorNone Successfully appended the MeshHeader to @p aFrameBuilder. 400 * @retval kErrorNoBufs Insufficient available buffers. 401 */ 402 Error AppendTo(FrameBuilder &aFrameBuilder) const; 403 404 /** 405 * Appends the Mesh Header to a given message. 406 * 407 * 408 * @param[out] aMessage A message to append the Mesh Header to. 409 * 410 * @retval kErrorNone Successfully appended the Mesh Header to @p aMessage. 411 * @retval kErrorNoBufs Insufficient available buffers to grow @p aMessage. 412 */ 413 Error AppendTo(Message &aMessage) const; 414 415 private: 416 static constexpr uint8_t kDispatch = 2 << 6; 417 static constexpr uint8_t kDispatchMask = 3 << 6; 418 static constexpr uint8_t kHopsLeftMask = 0x0f; 419 static constexpr uint8_t kSourceShort = 1 << 5; 420 static constexpr uint8_t kDestShort = 1 << 4; 421 static constexpr uint8_t kDeepHopsLeft = 0x0f; 422 423 // Dispatch byte + src + dest 424 static constexpr uint16_t kMinHeaderLength = sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint16_t); 425 static constexpr uint16_t kDeepHopsHeaderLength = kMinHeaderLength + sizeof(uint8_t); // min header + deep hops 426 427 uint16_t mSource; 428 uint16_t mDestination; 429 uint8_t mHopsLeft; 430 }; 431 432 /** 433 * Implements Fragment Header generation and parsing. 434 */ 435 class FragmentHeader 436 { 437 public: 438 OT_TOOL_PACKED_BEGIN 439 class FirstFrag 440 { 441 public: 442 /** 443 * Initializes the `FirstFrag`. 444 * 445 * @param[in] aSize The Datagram Size value. 446 * @param[in] aTag The Datagram Tag value. 447 */ Init(uint16_t aSize,uint16_t aTag)448 void Init(uint16_t aSize, uint16_t aTag) 449 { 450 mDispatchSize = BigEndian::HostSwap16(kFirstDispatch | (aSize & kSizeMask)); 451 mTag = BigEndian::HostSwap16(aTag); 452 } 453 454 private: 455 // 1 2 3 456 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 457 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 458 // |1 1 0 0 0| datagram_size | datagram_tag | 459 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 460 461 static constexpr uint16_t kFirstDispatch = 0xc000; // 0b11000_0000_0000_0000 462 463 uint16_t mDispatchSize; 464 uint16_t mTag; 465 } OT_TOOL_PACKED_END; 466 467 OT_TOOL_PACKED_BEGIN 468 class NextFrag 469 { 470 public: 471 /** 472 * Initializes the `NextFrag`. 473 * 474 * @param[in] aSize The Datagram Size value. 475 * @param[in] aTag The Datagram Tag value. 476 * @param[in] aOffset The Datagram Offset value. 477 */ Init(uint16_t aSize,uint16_t aTag,uint16_t aOffset)478 void Init(uint16_t aSize, uint16_t aTag, uint16_t aOffset) 479 { 480 mDispatchSize = BigEndian::HostSwap16(kNextDispatch | (aSize & kSizeMask)); 481 mTag = BigEndian::HostSwap16(aTag); 482 mOffset = static_cast<uint8_t>(aOffset >> 3); 483 } 484 485 private: 486 // 1 2 3 487 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 488 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 489 // |1 1 1 0 0| datagram_size | datagram_tag | 490 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 491 // |datagram_offset| 492 // +-+-+-+-+-+-+-+-+ 493 494 static constexpr uint16_t kNextDispatch = 0xe000; // 0b11100_0000_0000_0000 495 496 uint16_t mDispatchSize; 497 uint16_t mTag; 498 uint8_t mOffset; 499 } OT_TOOL_PACKED_END; 500 501 /** 502 * Indicates whether or not the header (in a given frame) is a Fragment Header. 503 * 504 * @note This method checks whether the frame has the minimum required length and that the first byte in 505 * header (dispatch byte) matches the Fragment Header dispatch value. It does not fully parse and validate the 506 * Fragment Header. `ParseFrom()` method can be used to fully parse and validate the header. 507 * 508 * @param[in] aFrameData The frame data. 509 * 510 * @retval TRUE If the header matches the Fragment Header dispatch value. 511 * @retval FALSE If the header does not match the Fragment Header dispatch value. 512 */ 513 static bool IsFragmentHeader(const FrameData &aFrameData); 514 515 /** 516 * Parses the Fragment Header from a given frame data. 517 * 518 * If the Fragment Header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes. 519 * 520 * @param[in,out] aFrameData The frame data to parse from. 521 * 522 * @retval kErrorNone Fragment Header parsed successfully. @p aFrameData is updated to skip over parsed header. 523 * @retval kErrorParse Fragment header could not be parsed. 524 */ 525 Error ParseFrom(FrameData &aFrameData); 526 527 /** 528 * Parses the Fragment Header from a message. 529 * 530 * @param[in] aMessage The message to read from. 531 * @param[in] aOffset The offset within the message to start reading from. 532 * @param[out] aHeaderLength A reference to a variable to output the parsed header length (on success). 533 * 534 * @retval kErrorNone Fragment Header parsed successfully. 535 * @retval kErrorParse Fragment header could not be parsed from @p aFrame. 536 */ 537 Error ParseFrom(const Message &aMessage, uint16_t aOffset, uint16_t &aHeaderLength); 538 539 /** 540 * Returns the Datagram Size value. 541 * 542 * @returns The Datagram Size value. 543 */ GetDatagramSize(void) const544 uint16_t GetDatagramSize(void) const { return mSize; } 545 546 /** 547 * Returns the Datagram Tag value. 548 * 549 * @returns The Datagram Tag value. 550 */ GetDatagramTag(void) const551 uint16_t GetDatagramTag(void) const { return mTag; } 552 553 /** 554 * Returns the Datagram Offset value. 555 * 556 * The returned offset value is always multiple of 8. 557 * 558 * @returns The Datagram Offset value (multiple of 8). 559 */ GetDatagramOffset(void) const560 uint16_t GetDatagramOffset(void) const { return mOffset; } 561 562 private: 563 static constexpr uint8_t kDispatch = 0xc0; // 0b1100_0000 564 static constexpr uint8_t kDispatchMask = 0xd8; // 0b1101_1000 accepts first (0b1100_0xxx) and next (0b1110_0xxx). 565 static constexpr uint8_t kOffsetFlag = 1 << 5; // Indicate first (no offset) vs. next (offset present) fragment. 566 567 static constexpr uint16_t kSizeMask = 0x7ff; // 0b0111_1111_1111 (first 11 bits). 568 static constexpr uint16_t kOffsetMask = 0xfff8; // Clears the last 3 bits to ensure offset is a multiple of 8. 569 570 static constexpr uint8_t kSizeIndex = 0; // Start index of Size field in the Fragment Header byte sequence. 571 static constexpr uint8_t kTagIndex = 2; // Start index of Tag field in the Fragment Header byte sequence. 572 static constexpr uint8_t kOffsetIndex = 4; // Start index of Offset field in the Fragment Header byte sequence. 573 574 static bool IsFragmentHeader(const uint8_t *aFrame, uint16_t aFrameLength); 575 576 Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength); 577 578 uint16_t mSize; 579 uint16_t mTag; 580 uint16_t mOffset; 581 }; 582 583 /** 584 * @} 585 */ 586 587 } // namespace Lowpan 588 } // namespace ot 589 590 #endif // LOWPAN_HPP_ 591