• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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