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