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 IPv6 packet processing. 32 */ 33 34 #ifndef IP6_HEADERS_HPP_ 35 #define IP6_HEADERS_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <stddef.h> 40 41 #include "common/clearable.hpp" 42 #include "common/encoding.hpp" 43 #include "common/message.hpp" 44 #include "net/ip6_address.hpp" 45 #include "net/ip6_types.hpp" 46 #include "net/netif.hpp" 47 #include "net/socket.hpp" 48 49 namespace ot { 50 51 /** 52 * @namespace ot::Ip6 53 * 54 * @brief 55 * This namespace includes definitions for IPv6 networking. 56 * 57 */ 58 namespace Ip6 { 59 60 using ot::Encoding::BigEndian::HostSwap16; 61 using ot::Encoding::BigEndian::HostSwap32; 62 63 /** 64 * @addtogroup core-ipv6 65 * 66 * @brief 67 * This module includes definitions for the IPv6 network layer. 68 * 69 * @{ 70 * 71 * @defgroup core-ip6-icmp6 ICMPv6 72 * @defgroup core-ip6-ip6 IPv6 73 * @defgroup core-ip6-mpl MPL 74 * @defgroup core-ip6-netif Network Interfaces 75 * 76 * @} 77 * 78 */ 79 80 /** 81 * @addtogroup core-ip6-ip6 82 * 83 * @brief 84 * This module includes definitions for core IPv6 networking. 85 * 86 * @{ 87 * 88 */ 89 90 /** 91 * This class implements IPv6 header generation and parsing. 92 * 93 */ 94 OT_TOOL_PACKED_BEGIN 95 class Header : public Clearable<Header> 96 { 97 public: 98 static constexpr uint8_t kPayloadLengthFieldOffset = 4; ///< Offset of Payload Length field in IPv6 header. 99 static constexpr uint8_t kNextHeaderFieldOffset = 6; ///< Offset of Next Header field in IPv6 header. 100 static constexpr uint8_t kHopLimitFieldOffset = 7; ///< Offset of Hop Limit field in IPv6 header. 101 static constexpr uint8_t kSourceFieldOffset = 8; ///< Offset of Source Address field in IPv6 header. 102 static constexpr uint8_t kDestinationFieldOffset = 24; ///< Offset of Destination Address field in IPv6 header. 103 104 /** 105 * This method initializes the Version to 6 and sets Traffic Class and Flow fields to zero. 106 * 107 * The other fields in the IPv6 header remain unchanged. 108 * 109 */ InitVersionTrafficClassFlow(void)110 void InitVersionTrafficClassFlow(void) { SetVerionTrafficClassFlow(kVersTcFlowInit); } 111 112 /** 113 * This method indicates whether or not the header appears to be well-formed. 114 * 115 * @retval TRUE If the header appears to be well-formed. 116 * @retval FALSE If the header does not appear to be well-formed. 117 * 118 */ 119 bool IsValid(void) const; 120 121 /** 122 * This method indicates whether or not the IPv6 Version is set to 6. 123 * 124 * @retval TRUE If the IPv6 Version is set to 6. 125 * @retval FALSE If the IPv6 Version is not set to 6. 126 * 127 */ IsVersion6(void) const128 bool IsVersion6(void) const { return (mVerTcFlow.m8[0] & kVersionMask) == kVersion6; } 129 130 /** 131 * This method gets the combination of Version, Traffic Class, and Flow fields as a 32-bit value. 132 * 133 * @returns The Version, Traffic Class, and Flow fields as a 32-bit value. 134 * 135 */ GetVerionTrafficClassFlow(void) const136 uint32_t GetVerionTrafficClassFlow(void) const { return HostSwap32(mVerTcFlow.m32); } 137 138 /** 139 * This method sets the combination of Version, Traffic Class, and Flow fields as a 32-bit value. 140 * 141 * @param[in] aVerTcFlow The Version, Traffic Class, and Flow fields as a 32-bit value. 142 * 143 */ SetVerionTrafficClassFlow(uint32_t aVerTcFlow)144 void SetVerionTrafficClassFlow(uint32_t aVerTcFlow) { mVerTcFlow.m32 = HostSwap32(aVerTcFlow); } 145 146 /** 147 * This method gets the Traffic Class field. 148 * 149 * @returns The Traffic Class field. 150 * 151 */ GetTrafficClass(void) const152 uint8_t GetTrafficClass(void) const 153 { 154 return static_cast<uint8_t>((HostSwap16(mVerTcFlow.m16[0]) & kTrafficClassMask) >> kTrafficClassOffset); 155 } 156 157 /** 158 * This method sets the Traffic Class filed. 159 * 160 * @param[in] aTc The Traffic Class value. 161 * 162 */ SetTrafficClass(uint8_t aTc)163 void SetTrafficClass(uint8_t aTc) 164 { 165 mVerTcFlow.m16[0] = HostSwap16((HostSwap16(mVerTcFlow.m16[0]) & ~kTrafficClassMask) | 166 ((static_cast<uint16_t>(aTc) << kTrafficClassOffset) & kTrafficClassMask)); 167 } 168 169 /** 170 * This method gets the 6-bit Differentiated Services Code Point (DSCP) from Traffic Class field. 171 * 172 * @returns The DSCP value. 173 * 174 */ GetDscp(void) const175 uint8_t GetDscp(void) const 176 { 177 return static_cast<uint8_t>((HostSwap16(mVerTcFlow.m16[0]) & kDscpMask) >> kDscpOffset); 178 } 179 180 /** 181 * This method sets 6-bit Differentiated Services Code Point (DSCP) in IPv6 header. 182 * 183 * @param[in] aDscp The DSCP value. 184 * 185 */ SetDscp(uint8_t aDscp)186 void SetDscp(uint8_t aDscp) 187 { 188 mVerTcFlow.m16[0] = HostSwap16((HostSwap16(mVerTcFlow.m16[0]) & ~kDscpMask) | 189 ((static_cast<uint16_t>(aDscp) << kDscpOffset) & kDscpMask)); 190 } 191 192 /** 193 * This method gets the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field. 194 * 195 * @returns The ECN value. 196 * 197 */ GetEcn(void) const198 Ecn GetEcn(void) const { return static_cast<Ecn>((mVerTcFlow.m8[1] & kEcnMask) >> kEcnOffset); } 199 200 /** 201 * This method sets the 2-bit Explicit Congestion Notification (ECN) in IPv6 header.. 202 * 203 * @param[in] aEcn The ECN value. 204 * 205 */ SetEcn(Ecn aEcn)206 void SetEcn(Ecn aEcn) { mVerTcFlow.m8[1] = (mVerTcFlow.m8[1] & ~kEcnMask) | ((aEcn << kEcnOffset) & kEcnMask); } 207 208 /** 209 * This method gets the 20-bit Flow field. 210 * 211 * @returns The Flow value. 212 * 213 */ GetFlow(void) const214 uint32_t GetFlow(void) const { return HostSwap32(mVerTcFlow.m32) & kFlowMask; } 215 216 /** 217 * This method sets the 20-bit Flow field in IPv6 header. 218 * 219 * @param[in] aFlow The Flow value. 220 * 221 */ SetFlow(uint32_t aFlow)222 void SetFlow(uint32_t aFlow) 223 { 224 mVerTcFlow.m32 = HostSwap32((HostSwap32(mVerTcFlow.m32) & ~kFlowMask) | (aFlow & kFlowMask)); 225 } 226 227 /** 228 * This method returns the IPv6 Payload Length value. 229 * 230 * @returns The IPv6 Payload Length value. 231 * 232 */ GetPayloadLength(void) const233 uint16_t GetPayloadLength(void) const { return HostSwap16(mPayloadLength); } 234 235 /** 236 * This method sets the IPv6 Payload Length value. 237 * 238 * @param[in] aLength The IPv6 Payload Length value. 239 * 240 */ SetPayloadLength(uint16_t aLength)241 void SetPayloadLength(uint16_t aLength) { mPayloadLength = HostSwap16(aLength); } 242 243 /** 244 * This method returns the IPv6 Next Header value. 245 * 246 * @returns The IPv6 Next Header value. 247 * 248 */ GetNextHeader(void) const249 uint8_t GetNextHeader(void) const { return mNextHeader; } 250 251 /** 252 * This method sets the IPv6 Next Header value. 253 * 254 * @param[in] aNextHeader The IPv6 Next Header value. 255 * 256 */ SetNextHeader(uint8_t aNextHeader)257 void SetNextHeader(uint8_t aNextHeader) { mNextHeader = aNextHeader; } 258 259 /** 260 * This method returns the IPv6 Hop Limit value. 261 * 262 * @returns The IPv6 Hop Limit value. 263 * 264 */ GetHopLimit(void) const265 uint8_t GetHopLimit(void) const { return mHopLimit; } 266 267 /** 268 * This method sets the IPv6 Hop Limit value. 269 * 270 * @param[in] aHopLimit The IPv6 Hop Limit value. 271 * 272 */ SetHopLimit(uint8_t aHopLimit)273 void SetHopLimit(uint8_t aHopLimit) { mHopLimit = aHopLimit; } 274 275 /** 276 * This method returns the IPv6 Source address. 277 * 278 * @returns A reference to the IPv6 Source address. 279 * 280 */ GetSource(void)281 Address &GetSource(void) { return mSource; } 282 283 /** 284 * This method returns the IPv6 Source address. 285 * 286 * @returns A reference to the IPv6 Source address. 287 * 288 */ GetSource(void) const289 const Address &GetSource(void) const { return mSource; } 290 291 /** 292 * This method sets the IPv6 Source address. 293 * 294 * @param[in] aSource A reference to the IPv6 Source address. 295 * 296 */ SetSource(const Address & aSource)297 void SetSource(const Address &aSource) { mSource = aSource; } 298 299 /** 300 * This method returns the IPv6 Destination address. 301 * 302 * @returns A reference to the IPv6 Destination address. 303 * 304 */ GetDestination(void)305 Address &GetDestination(void) { return mDestination; } 306 307 /** 308 * This method returns the IPv6 Destination address. 309 * 310 * @returns A reference to the IPv6 Destination address. 311 * 312 */ GetDestination(void) const313 const Address &GetDestination(void) const { return mDestination; } 314 315 /** 316 * This method sets the IPv6 Destination address. 317 * 318 * @param[in] aDestination A reference to the IPv6 Destination address. 319 * 320 */ SetDestination(const Address & aDestination)321 void SetDestination(const Address &aDestination) { mDestination = aDestination; } 322 323 /** 324 * This method parses and validates the IPv6 header from a given message. 325 * 326 * The header is read from @p aMessage at offset zero. 327 * 328 * @param[in] aMessage The IPv6 message. 329 * 330 * @retval kErrorNone Successfully parsed the IPv6 header from @p aMessage. 331 * @retval kErrorParse Malformed IPv6 header or message (e.g., message does not contained expected payload length). 332 * 333 */ 334 Error ParseFrom(const Message &aMessage); 335 336 private: 337 // IPv6 header `mVerTcFlow` field: 338 // 339 // | m16[0] | m16[1] | 340 // | m8[0] | m8[1] | m8[2] | m8[3] | 341 // +---------------+---------------+---------------+---------------+ 342 // |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| 343 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 344 // |Version| DSCP |ECN| Flow Label | 345 // | | Traffic Class | | 346 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 347 348 static constexpr uint8_t kVersion6 = 0x60; // Use with `mVerTcFlow.m8[0]` 349 static constexpr uint8_t kVersionMask = 0xf0; // Use with `mVerTcFlow.m8[0]` 350 static constexpr uint8_t kTrafficClassOffset = 4; // Use with `mVerTcFlow.m16[0]` 351 static constexpr uint16_t kTrafficClassMask = 0x0ff0; // Use with `mVerTcFlow.m16[0]` 352 static constexpr uint8_t kDscpOffset = 6; // Use with `mVerTcFlow.m16[0]` 353 static constexpr uint16_t kDscpMask = 0x0fc0; // Use with `mVerTcFlow.m16[0]` 354 static constexpr uint8_t kEcnOffset = 4; // Use with `mVerTcFlow.m8[1]` 355 static constexpr uint8_t kEcnMask = 0x30; // Use with `mVerTcFlow.m8[1]` 356 static constexpr uint32_t kFlowMask = 0x000fffff; // Use with `mVerTcFlow.m32` 357 static constexpr uint32_t kVersTcFlowInit = 0x60000000; // Version 6, TC and flow zero. 358 359 union OT_TOOL_PACKED_FIELD 360 { 361 uint8_t m8[sizeof(uint32_t) / sizeof(uint8_t)]; 362 uint16_t m16[sizeof(uint32_t) / sizeof(uint16_t)]; 363 uint32_t m32; 364 } mVerTcFlow; 365 uint16_t mPayloadLength; 366 uint8_t mNextHeader; 367 uint8_t mHopLimit; 368 Address mSource; 369 Address mDestination; 370 } OT_TOOL_PACKED_END; 371 372 /** 373 * This class implements IPv6 Extension Header generation and processing. 374 * 375 */ 376 OT_TOOL_PACKED_BEGIN 377 class ExtensionHeader 378 { 379 public: 380 /** 381 * This method returns the IPv6 Next Header value. 382 * 383 * @returns The IPv6 Next Header value. 384 * 385 */ GetNextHeader(void) const386 uint8_t GetNextHeader(void) const { return mNextHeader; } 387 388 /** 389 * This method sets the IPv6 Next Header value. 390 * 391 * @param[in] aNextHeader The IPv6 Next Header value. 392 * 393 */ SetNextHeader(uint8_t aNextHeader)394 void SetNextHeader(uint8_t aNextHeader) { mNextHeader = aNextHeader; } 395 396 /** 397 * This method returns the IPv6 Header Extension Length value. 398 * 399 * @returns The IPv6 Header Extension Length value. 400 * 401 */ GetLength(void) const402 uint8_t GetLength(void) const { return mLength; } 403 404 /** 405 * This method sets the IPv6 Header Extension Length value. 406 * 407 * @param[in] aLength The IPv6 Header Extension Length value. 408 * 409 */ SetLength(uint8_t aLength)410 void SetLength(uint8_t aLength) { mLength = aLength; } 411 412 private: 413 uint8_t mNextHeader; 414 uint8_t mLength; 415 } OT_TOOL_PACKED_END; 416 417 /** 418 * This class implements IPv6 Hop-by-Hop Options Header generation and parsing. 419 * 420 */ 421 OT_TOOL_PACKED_BEGIN 422 class HopByHopHeader : public ExtensionHeader 423 { 424 } OT_TOOL_PACKED_END; 425 426 /** 427 * This class implements IPv6 Options generation and parsing. 428 * 429 */ 430 OT_TOOL_PACKED_BEGIN 431 class OptionHeader 432 { 433 public: 434 /** 435 * Default constructor. 436 * 437 */ OptionHeader(void)438 OptionHeader(void) 439 : mType(0) 440 , mLength(0) 441 { 442 } 443 444 /** 445 * This method returns the IPv6 Option Type value. 446 * 447 * @returns The IPv6 Option Type value. 448 * 449 */ GetType(void) const450 uint8_t GetType(void) const { return mType; } 451 452 /** 453 * This method sets the IPv6 Option Type value. 454 * 455 * @param[in] aType The IPv6 Option Type value. 456 * 457 */ SetType(uint8_t aType)458 void SetType(uint8_t aType) { mType = aType; } 459 460 /** 461 * IPv6 Option Type actions for unrecognized IPv6 Options. 462 * 463 */ 464 enum Action : uint8_t 465 { 466 kActionSkip = 0x00, ///< skip over this option and continue processing the header 467 kActionDiscard = 0x40, ///< discard the packet 468 kActionForceIcmp = 0x80, ///< discard the packet and forcibly send an ICMP Parameter Problem 469 kActionIcmp = 0xc0, ///< discard packet and conditionally send an ICMP Parameter Problem 470 }; 471 472 /** 473 * This method returns the IPv6 Option action for unrecognized IPv6 Options. 474 * 475 * @returns The IPv6 Option action for unrecognized IPv6 Options. 476 * 477 */ GetAction(void) const478 Action GetAction(void) const { return static_cast<Action>(mType & kActionMask); } 479 480 /** 481 * This method returns the IPv6 Option Length value. 482 * 483 * @returns The IPv6 Option Length value. 484 * 485 */ GetLength(void) const486 uint8_t GetLength(void) const { return mLength; } 487 488 /** 489 * This method sets the IPv6 Option Length value. 490 * 491 * @param[in] aLength The IPv6 Option Length value. 492 * 493 */ SetLength(uint8_t aLength)494 void SetLength(uint8_t aLength) { mLength = aLength; } 495 496 private: 497 static constexpr uint8_t kActionMask = 0xc0; 498 499 uint8_t mType; 500 uint8_t mLength; 501 } OT_TOOL_PACKED_END; 502 503 /** 504 * This class implements IPv6 PadN Option generation and parsing. 505 * 506 */ 507 OT_TOOL_PACKED_BEGIN 508 class OptionPadN : public OptionHeader 509 { 510 public: 511 static constexpr uint8_t kType = 0x01; ///< PadN type 512 static constexpr uint8_t kData = 0x00; ///< PadN specific data 513 static constexpr uint8_t kMaxLength = 0x05; ///< Maximum length of PadN option data 514 515 /** 516 * This method initializes the PadN header. 517 * 518 * @param[in] aPadLength The length of needed padding. Allowed value from 519 * range 2-7. 520 * 521 */ Init(uint8_t aPadLength)522 void Init(uint8_t aPadLength) 523 { 524 SetType(kType); 525 SetLength(aPadLength - sizeof(OptionHeader)); 526 memset(mPad, kData, aPadLength - sizeof(OptionHeader)); 527 } 528 529 /** 530 * This method returns the total IPv6 Option Length value including option 531 * header. 532 * 533 * @returns The total IPv6 Option Length. 534 * 535 */ GetTotalLength(void) const536 uint8_t GetTotalLength(void) const { return GetLength() + sizeof(OptionHeader); } 537 538 private: 539 uint8_t mPad[kMaxLength]; 540 } OT_TOOL_PACKED_END; 541 542 /** 543 * This class implements IPv6 Pad1 Option generation and parsing. Pad1 does not follow default option header structure. 544 * 545 */ 546 OT_TOOL_PACKED_BEGIN 547 class OptionPad1 548 { 549 public: 550 static constexpr uint8_t kType = 0x00; 551 552 /** 553 * This method initializes the Pad1 header. 554 * 555 */ Init(void)556 void Init(void) { mType = kType; } 557 558 private: 559 uint8_t mType; 560 } OT_TOOL_PACKED_END; 561 562 /** 563 * This class implements IPv6 Fragment Header generation and parsing. 564 * 565 */ 566 OT_TOOL_PACKED_BEGIN 567 class FragmentHeader 568 { 569 public: 570 /** 571 * This method initializes the IPv6 Fragment header. 572 * 573 */ Init(void)574 void Init(void) 575 { 576 mReserved = 0; 577 mOffsetMore = 0; 578 mIdentification = 0; 579 } 580 581 /** 582 * This method returns the IPv6 Next Header value. 583 * 584 * @returns The IPv6 Next Header value. 585 * 586 */ GetNextHeader(void) const587 uint8_t GetNextHeader(void) const { return mNextHeader; } 588 589 /** 590 * This method sets the IPv6 Next Header value. 591 * 592 * @param[in] aNextHeader The IPv6 Next Header value. 593 * 594 */ SetNextHeader(uint8_t aNextHeader)595 void SetNextHeader(uint8_t aNextHeader) { mNextHeader = aNextHeader; } 596 597 /** 598 * This method returns the Fragment Offset value. 599 * 600 * @returns The Fragment Offset value. 601 * 602 */ GetOffset(void) const603 uint16_t GetOffset(void) const { return (HostSwap16(mOffsetMore) & kOffsetMask) >> kOffsetOffset; } 604 605 /** 606 * This method sets the Fragment Offset value. 607 * 608 * @param[in] aOffset The Fragment Offset value. 609 */ SetOffset(uint16_t aOffset)610 void SetOffset(uint16_t aOffset) 611 { 612 uint16_t tmp = HostSwap16(mOffsetMore); 613 tmp = (tmp & ~kOffsetMask) | ((aOffset << kOffsetOffset) & kOffsetMask); 614 mOffsetMore = HostSwap16(tmp); 615 } 616 617 /** 618 * This method returns the M flag value. 619 * 620 * @returns The M flag value. 621 * 622 */ IsMoreFlagSet(void) const623 bool IsMoreFlagSet(void) const { return HostSwap16(mOffsetMore) & kMoreFlag; } 624 625 /** 626 * This method clears the M flag value. 627 * 628 */ ClearMoreFlag(void)629 void ClearMoreFlag(void) { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) & ~kMoreFlag); } 630 631 /** 632 * This method sets the M flag value. 633 * 634 */ SetMoreFlag(void)635 void SetMoreFlag(void) { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) | kMoreFlag); } 636 637 /** 638 * This method returns the frame identification. 639 * 640 * @returns The frame identification. 641 * 642 */ GetIdentification(void) const643 uint32_t GetIdentification(void) const { return mIdentification; } 644 645 /** 646 * This method sets the frame identification. 647 * 648 * @param[in] aIdentification The fragment identification value. 649 */ SetIdentification(uint32_t aIdentification)650 void SetIdentification(uint32_t aIdentification) { mIdentification = aIdentification; } 651 652 /** 653 * This method returns the next valid payload length for a fragment. 654 * 655 * @param[in] aLength The payload length to be validated for a fragment. 656 * 657 * @returns Valid IPv6 fragment payload length. 658 * 659 */ MakeDivisibleByEight(uint16_t aLength)660 static inline uint16_t MakeDivisibleByEight(uint16_t aLength) { return aLength & 0xfff8; } 661 662 /** 663 * This method converts the fragment offset of 8-octet units into bytes. 664 * 665 * @param[in] aOffset The fragment offset in 8-octet units. 666 * 667 * @returns The fragment offset in bytes. 668 * 669 */ FragmentOffsetToBytes(uint16_t aOffset)670 static inline uint16_t FragmentOffsetToBytes(uint16_t aOffset) { return static_cast<uint16_t>(aOffset << 3); } 671 672 /** 673 * This method converts a fragment offset in bytes into a fragment offset in 8-octet units. 674 * 675 * @param[in] aOffset The fragment offset in bytes. 676 * 677 * @returns The fragment offset in 8-octet units. 678 */ BytesToFragmentOffset(uint16_t aOffset)679 static inline uint16_t BytesToFragmentOffset(uint16_t aOffset) { return aOffset >> 3; } 680 681 private: 682 static constexpr uint8_t kOffsetOffset = 3; 683 static constexpr uint16_t kOffsetMask = 0xfff8; 684 static constexpr uint16_t kMoreFlag = 1; 685 686 uint8_t mNextHeader; 687 uint8_t mReserved; 688 uint16_t mOffsetMore; 689 uint32_t mIdentification; 690 } OT_TOOL_PACKED_END; 691 692 /** 693 * @} 694 * 695 */ 696 697 } // namespace Ip6 698 } // namespace ot 699 700 #endif // IP6_HEADERS_HPP_ 701