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 generating and processing MLE TLVs.
32  */
33 
34 #ifndef MLE_TLVS_HPP_
35 #define MLE_TLVS_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/encoding.hpp"
40 #include "common/message.hpp"
41 #include "common/preference.hpp"
42 #include "common/tlvs.hpp"
43 #include "meshcop/timestamp.hpp"
44 #include "net/ip6_address.hpp"
45 #include "thread/link_metrics_tlvs.hpp"
46 #include "thread/mle_types.hpp"
47 
48 namespace ot {
49 
50 namespace Mle {
51 
52 /**
53  * @addtogroup core-mle-tlvs
54  *
55  * @brief
56  *   This module includes definitions for generating and processing MLE TLVs.
57  *
58  * @{
59  */
60 
61 /**
62  * Implements MLE TLV generation and parsing.
63  */
64 OT_TOOL_PACKED_BEGIN
65 class Tlv : public ot::Tlv
66 {
67 public:
68     /**
69      * MLE TLV Types.
70      */
71     enum Type : uint8_t
72     {
73         kSourceAddress         = 0,  ///< Source Address TLV
74         kMode                  = 1,  ///< Mode TLV
75         kTimeout               = 2,  ///< Timeout TLV
76         kChallenge             = 3,  ///< Challenge TLV
77         kResponse              = 4,  ///< Response TLV
78         kLinkFrameCounter      = 5,  ///< Link-Layer Frame Counter TLV
79         kLinkQuality           = 6,  ///< Link Quality TLV
80         kNetworkParameter      = 7,  ///< Network Parameter TLV
81         kMleFrameCounter       = 8,  ///< MLE Frame Counter TLV
82         kRoute                 = 9,  ///< Route64 TLV
83         kAddress16             = 10, ///< Address16 TLV
84         kLeaderData            = 11, ///< Leader Data TLV
85         kNetworkData           = 12, ///< Network Data TLV
86         kTlvRequest            = 13, ///< TLV Request TLV
87         kScanMask              = 14, ///< Scan Mask TLV
88         kConnectivity          = 15, ///< Connectivity TLV
89         kLinkMargin            = 16, ///< Link Margin TLV
90         kStatus                = 17, ///< Status TLV
91         kVersion               = 18, ///< Version TLV
92         kAddressRegistration   = 19, ///< Address Registration TLV
93         kChannel               = 20, ///< Channel TLV
94         kPanId                 = 21, ///< PAN ID TLV
95         kActiveTimestamp       = 22, ///< Active Timestamp TLV
96         kPendingTimestamp      = 23, ///< Pending Timestamp TLV
97         kActiveDataset         = 24, ///< Active Operational Dataset TLV
98         kPendingDataset        = 25, ///< Pending Operational Dataset TLV
99         kDiscovery             = 26, ///< Thread Discovery TLV
100         kSupervisionInterval   = 27, ///< Supervision Interval TLV
101         kWakeupChannel         = 74, ///< Wakeup Channel TLV
102         kCslChannel            = 80, ///< CSL Channel TLV
103         kCslTimeout            = 85, ///< CSL Timeout TLV
104         kCslClockAccuracy      = 86, ///< CSL Clock Accuracy TLV
105         kLinkMetricsQuery      = 87, ///< Link Metrics Query TLV
106         kLinkMetricsManagement = 88, ///< Link Metrics Management TLV
107         kLinkMetricsReport     = 89, ///< Link Metrics Report TLV
108         kLinkProbe             = 90, ///< Link Probe TLV
109 
110         /**
111          * Applicable/Required only when time synchronization service
112          * (`OPENTHREAD_CONFIG_TIME_SYNC_ENABLE`) is enabled.
113          */
114         kTimeRequest   = 252, ///< Time Request TLV
115         kTimeParameter = 253, ///< Time Parameter TLV
116         kXtalAccuracy  = 254, ///< XTAL Accuracy TLV
117 
118         kInvalid = 255,
119     };
120 
121     /**
122      * Returns the Type value.
123      *
124      * @returns The Type value.
125      */
GetType(void) const126     Type GetType(void) const { return static_cast<Type>(ot::Tlv::GetType()); }
127 
128     /**
129      * Sets the Type value.
130      *
131      * @param[in]  aType  The Type value.
132      */
SetType(Type aType)133     void SetType(Type aType) { ot::Tlv::SetType(static_cast<uint8_t>(aType)); }
134 
135 } OT_TOOL_PACKED_END;
136 
137 /**
138  * Defines Source Address TLV constants and types.
139  */
140 typedef UintTlvInfo<Tlv::kSourceAddress, uint16_t> SourceAddressTlv;
141 
142 /**
143  * Defines Mode TLV constants and types.
144  */
145 typedef UintTlvInfo<Tlv::kMode, uint8_t> ModeTlv;
146 
147 /**
148  * Defines Timeout TLV constants and types.
149  */
150 typedef UintTlvInfo<Tlv::kTimeout, uint32_t> TimeoutTlv;
151 
152 /**
153  * Defines Challenge TLV constants and types.
154  */
155 typedef TlvInfo<Tlv::kChallenge> ChallengeTlv;
156 
157 /**
158  * Defines Response TLV constants and types.
159  */
160 typedef TlvInfo<Tlv::kResponse> ResponseTlv;
161 
162 /**
163  * Defines Link Frame Counter TLV constants and types.
164  */
165 typedef UintTlvInfo<Tlv::kLinkFrameCounter, uint32_t> LinkFrameCounterTlv;
166 
167 /**
168  * Defines MLE Frame Counter TLV constants and types.
169  */
170 typedef UintTlvInfo<Tlv::kMleFrameCounter, uint32_t> MleFrameCounterTlv;
171 
172 /**
173  * Defines Address16 TLV constants and types.
174  */
175 typedef UintTlvInfo<Tlv::kAddress16, uint16_t> Address16Tlv;
176 
177 /**
178  * Defines Network Data TLV constants and types.
179  */
180 typedef TlvInfo<Tlv::kNetworkData> NetworkDataTlv;
181 
182 /**
183  * Defines TLV Request TLV constants and types.
184  */
185 typedef TlvInfo<Tlv::kTlvRequest> TlvRequestTlv;
186 
187 /**
188  * Defines Link Margin TLV constants and types.
189  */
190 typedef UintTlvInfo<Tlv::kLinkMargin, uint8_t> LinkMarginTlv;
191 
192 /**
193  * Defines Version TLV constants and types.
194  */
195 typedef UintTlvInfo<Tlv::kVersion, uint16_t> VersionTlv;
196 
197 /**
198  * Defines PAN ID TLV constants and types.
199  */
200 typedef UintTlvInfo<Tlv::kPanId, uint16_t> PanIdTlv;
201 
202 /**
203  * Defines Active Timestamp TLV constants and types.
204  */
205 typedef SimpleTlvInfo<Tlv::kActiveTimestamp, MeshCoP::Timestamp> ActiveTimestampTlv;
206 
207 /**
208  * Defines Pending Timestamp TLV constants and types.
209  */
210 typedef SimpleTlvInfo<Tlv::kPendingTimestamp, MeshCoP::Timestamp> PendingTimestampTlv;
211 
212 /**
213  * Defines Timeout TLV constants and types.
214  */
215 typedef UintTlvInfo<Tlv::kSupervisionInterval, uint16_t> SupervisionIntervalTlv;
216 
217 /**
218  * Defines CSL Timeout TLV constants and types.
219  */
220 typedef UintTlvInfo<Tlv::kCslTimeout, uint32_t> CslTimeoutTlv;
221 
222 /**
223  * Defines XTAL Accuracy TLV constants and types.
224  */
225 typedef UintTlvInfo<Tlv::kXtalAccuracy, uint16_t> XtalAccuracyTlv;
226 
227 #if !OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
228 
229 /**
230  * Implements Route TLV generation and parsing.
231  */
232 OT_TOOL_PACKED_BEGIN
233 class RouteTlv : public Tlv, public TlvInfo<Tlv::kRoute>
234 {
235 public:
236     /**
237      * Initializes the TLV.
238      */
239     void Init(void);
240 
241     /**
242      * Indicates whether or not the TLV appears to be well-formed.
243      *
244      * @retval TRUE   If the TLV appears to be well-formed.
245      * @retval FALSE  If the TLV does not appear to be well-formed.
246      */
247     bool IsValid(void) const;
248 
249     /**
250      * Returns the Router ID Sequence value.
251      *
252      * @returns The Router ID Sequence value.
253      */
GetRouterIdSequence(void) const254     uint8_t GetRouterIdSequence(void) const { return mRouterIdSequence; }
255 
256     /**
257      * Sets the Router ID Sequence value.
258      *
259      * @param[in]  aSequence  The Router ID Sequence value.
260      */
SetRouterIdSequence(uint8_t aSequence)261     void SetRouterIdSequence(uint8_t aSequence) { mRouterIdSequence = aSequence; }
262 
263     /**
264      * Gets the Router ID Mask.
265      */
GetRouterIdMask(void) const266     const RouterIdSet &GetRouterIdMask(void) const { return mRouterIdMask; }
267 
268     /**
269      * Sets the Router ID Mask.
270      *
271      * @param[in]  aRouterIdSet The Router ID Mask to set.
272      */
SetRouterIdMask(const RouterIdSet & aRouterIdSet)273     void SetRouterIdMask(const RouterIdSet &aRouterIdSet) { mRouterIdMask = aRouterIdSet; }
274 
275     /**
276      * Indicates whether or not a Router ID bit is set.
277      *
278      * @param[in]  aRouterId  The Router ID bit.
279      *
280      * @retval TRUE   If the Router ID bit is set.
281      * @retval FALSE  If the Router ID bit is not set.
282      */
IsRouterIdSet(uint8_t aRouterId) const283     bool IsRouterIdSet(uint8_t aRouterId) const { return mRouterIdMask.Contains(aRouterId); }
284 
285     /**
286      * Indicates whether the `RouteTlv` is a singleton, i.e., only one router is allocated.
287      *
288      * @retval TRUE   It is a singleton.
289      * @retval FALSE  It is not a singleton.
290      */
IsSingleton(void) const291     bool IsSingleton(void) const { return IsValid() && (mRouterIdMask.GetNumberOfAllocatedIds() <= 1); }
292 
293     /**
294      * Returns the Route Data Length value.
295      *
296      * @returns The Route Data Length value.
297      */
GetRouteDataLength(void) const298     uint8_t GetRouteDataLength(void) const { return GetLength() - sizeof(mRouterIdSequence) - sizeof(mRouterIdMask); }
299 
300     /**
301      * Sets the Route Data Length value.
302      *
303      * @param[in]  aLength  The Route Data Length value.
304      */
SetRouteDataLength(uint8_t aLength)305     void SetRouteDataLength(uint8_t aLength) { SetLength(sizeof(mRouterIdSequence) + sizeof(mRouterIdMask) + aLength); }
306 
307     /**
308      * Returns the Route Cost value for a given Router index.
309      *
310      * @param[in]  aRouterIndex  The Router index.
311      *
312      * @returns The Route Cost value for a given Router index.
313      */
GetRouteCost(uint8_t aRouterIndex) const314     uint8_t GetRouteCost(uint8_t aRouterIndex) const { return mRouteData[aRouterIndex] & kRouteCostMask; }
315 
316     /**
317      * Returns the Link Quality In value for a given Router index.
318      *
319      * @param[in]  aRouterIndex  The Router index.
320      *
321      * @returns The Link Quality In value for a given Router index.
322      */
GetLinkQualityIn(uint8_t aRouterIndex) const323     LinkQuality GetLinkQualityIn(uint8_t aRouterIndex) const
324     {
325         return static_cast<LinkQuality>((mRouteData[aRouterIndex] & kLinkQualityInMask) >> kLinkQualityInOffset);
326     }
327 
328     /**
329      * Returns the Link Quality Out value for a given Router index.
330      *
331      * @param[in]  aRouterIndex  The Router index.
332      *
333      * @returns The Link Quality Out value for a given Router index.
334      */
GetLinkQualityOut(uint8_t aRouterIndex) const335     LinkQuality GetLinkQualityOut(uint8_t aRouterIndex) const
336     {
337         return static_cast<LinkQuality>((mRouteData[aRouterIndex] & kLinkQualityOutMask) >> kLinkQualityOutOffset);
338     }
339 
340     /**
341      * Sets the Route Data (Link Quality In/Out and Route Cost) for a given Router index.
342      *
343      * @param[in]  aRouterIndex    The Router index.
344      * @param[in]  aLinkQualityIn  The Link Quality In value.
345      * @param[in]  aLinkQualityOut The Link Quality Out value.
346      * @param[in]  aRouteCost      The Route Cost value.
347      */
SetRouteData(uint8_t aRouterIndex,LinkQuality aLinkQualityIn,LinkQuality aLinkQualityOut,uint8_t aRouteCost)348     void SetRouteData(uint8_t aRouterIndex, LinkQuality aLinkQualityIn, LinkQuality aLinkQualityOut, uint8_t aRouteCost)
349     {
350         mRouteData[aRouterIndex] = (((aLinkQualityIn << kLinkQualityInOffset) & kLinkQualityInMask) |
351                                     ((aLinkQualityOut << kLinkQualityOutOffset) & kLinkQualityOutMask) |
352                                     ((aRouteCost << kRouteCostOffset) & kRouteCostMask));
353     }
354 
355 private:
356     static constexpr uint8_t kLinkQualityOutOffset = 6;
357     static constexpr uint8_t kLinkQualityOutMask   = 3 << kLinkQualityOutOffset;
358     static constexpr uint8_t kLinkQualityInOffset  = 4;
359     static constexpr uint8_t kLinkQualityInMask    = 3 << kLinkQualityInOffset;
360     static constexpr uint8_t kRouteCostOffset      = 0;
361     static constexpr uint8_t kRouteCostMask        = 0xf << kRouteCostOffset;
362 
363     uint8_t     mRouterIdSequence;
364     RouterIdSet mRouterIdMask;
365     uint8_t     mRouteData[kMaxRouterId + 1];
366 } OT_TOOL_PACKED_END;
367 
368 #else // OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
369 
370 /**
371  * Implements Route TLV generation and parsing.
372  */
373 OT_TOOL_PACKED_BEGIN
374 class RouteTlv : public Tlv, public TlvInfo<Tlv::kRoute>
375 {
376 public:
377     /**
378      * Initializes the TLV.
379      */
Init(void)380     void Init(void)
381     {
382         SetType(kRoute);
383         SetLength(sizeof(*this) - sizeof(Tlv));
384     }
385 
386     /**
387      * Indicates whether or not the TLV appears to be well-formed.
388      *
389      * @retval TRUE   If the TLV appears to be well-formed.
390      * @retval FALSE  If the TLV does not appear to be well-formed.
391      */
IsValid(void) const392     bool IsValid(void) const { return GetLength() >= sizeof(mRouterIdSequence) + sizeof(mRouterIdMask); }
393 
394     /**
395      * Returns the Router ID Sequence value.
396      *
397      * @returns The Router ID Sequence value.
398      */
GetRouterIdSequence(void) const399     uint8_t GetRouterIdSequence(void) const { return mRouterIdSequence; }
400 
401     /**
402      * Sets the Router ID Sequence value.
403      *
404      * @param[in]  aSequence  The Router ID Sequence value.
405      */
SetRouterIdSequence(uint8_t aSequence)406     void SetRouterIdSequence(uint8_t aSequence) { mRouterIdSequence = aSequence; }
407 
408     /**
409      * Gets the Router ID Mask.
410      */
GetRouterIdMask(void) const411     const RouterIdSet &GetRouterIdMask(void) const { return mRouterIdMask; }
412 
413     /**
414      * Sets the Router ID Mask.
415      *
416      * @param[in]  aRouterIdSet The Router ID Mask to set.
417      */
SetRouterIdMask(const RouterIdSet & aRouterIdSet)418     void SetRouterIdMask(const RouterIdSet &aRouterIdSet) { mRouterIdMask = aRouterIdSet; }
419 
420     /**
421      * Indicates whether or not a Router ID bit is set.
422      *
423      * @param[in]  aRouterId  The Router ID.
424      *
425      * @retval TRUE   If the Router ID bit is set.
426      * @retval FALSE  If the Router ID bit is not set.
427      */
IsRouterIdSet(uint8_t aRouterId) const428     bool IsRouterIdSet(uint8_t aRouterId) const { return mRouterIdMask.Contains(aRouterId); }
429 
430     /**
431      * Indicates whether the `RouteTlv` is a singleton, i.e., only one router is allocated.
432      *
433      * @retval TRUE   It is a singleton.
434      * @retval FALSE  It is not a singleton.
435      */
IsSingleton(void) const436     bool IsSingleton(void) const { return IsValid() && (mRouterIdMask.GetNumberOfAllocatedIds() <= 1); }
437 
438     /**
439      * Sets the Router ID bit.
440      *
441      * @param[in]  aRouterId  The Router ID bit to set.
442      */
SetRouterId(uint8_t aRouterId)443     void SetRouterId(uint8_t aRouterId) { mRouterIdMask.Add(aRouterId); }
444 
445     /**
446      * Returns the Route Data Length value.
447      *
448      * @returns The Route Data Length value in bytes
449      */
GetRouteDataLength(void) const450     uint8_t GetRouteDataLength(void) const { return GetLength() - sizeof(mRouterIdSequence) - sizeof(mRouterIdMask); }
451 
452     /**
453      * Sets the Route Data Length value.
454      *
455      * @param[in]  aLength  The Route Data Length value in number of router entries
456      */
SetRouteDataLength(uint8_t aLength)457     void SetRouteDataLength(uint8_t aLength)
458     {
459         SetLength(sizeof(mRouterIdSequence) + sizeof(mRouterIdMask) + aLength + (aLength + 1) / 2);
460     }
461 
462     /**
463      * Returns the Route Cost value for a given Router index.
464      *
465      * @param[in]  aRouterIndex  The Router index.
466      *
467      * @returns The Route Cost value for a given Router index.
468      */
GetRouteCost(uint8_t aRouterIndex) const469     uint8_t GetRouteCost(uint8_t aRouterIndex) const
470     {
471         if (aRouterIndex & 1)
472         {
473             return mRouteData[aRouterIndex + aRouterIndex / 2 + 1];
474         }
475         else
476         {
477             return static_cast<uint8_t>((mRouteData[aRouterIndex + aRouterIndex / 2] & kRouteCostMask)
478                                         << kOddEntryOffset) |
479                    ((mRouteData[aRouterIndex + aRouterIndex / 2 + 1] &
480                      static_cast<uint8_t>(kRouteCostMask << kOddEntryOffset)) >>
481                     kOddEntryOffset);
482         }
483     }
484 
485     /**
486      * Returns the Link Quality In value for a given Router index.
487      *
488      * @param[in]  aRouterIndex  The Router index.
489      *
490      * @returns The Link Quality In value for a given Router index.
491      */
GetLinkQualityIn(uint8_t aRouterIndex) const492     LinkQuality GetLinkQualityIn(uint8_t aRouterIndex) const
493     {
494         int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0);
495         return static_cast<LinkQuality>(
496             (mRouteData[aRouterIndex + aRouterIndex / 2] & (kLinkQualityInMask >> offset)) >>
497             (kLinkQualityInOffset - offset));
498     }
499 
500     /**
501      * Returns the Link Quality Out value for a given Router index.
502      *
503      * @param[in]  aRouterIndex  The Router index.
504      *
505      * @returns The Link Quality Out value for a given Router index.
506      */
GetLinkQualityOut(uint8_t aRouterIndex) const507     LinkQuality GetLinkQualityOut(uint8_t aRouterIndex) const
508     {
509         int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0);
510         return static_cast<LinkQuality>(
511             (mRouteData[aRouterIndex + aRouterIndex / 2] & (kLinkQualityOutMask >> offset)) >>
512             (kLinkQualityOutOffset - offset));
513     }
514 
515     /**
516      * Sets the Route Data (Link Quality In/Out and Route Cost) for a given Router index.
517      *
518      * @param[in]  aRouterIndex    The Router index.
519      * @param[in]  aLinkQualityIn  The Link Quality In value.
520      * @param[in]  aLinkQualityOut The Link Quality Out value.
521      * @param[in]  aRouteCost      The Route Cost value.
522      */
SetRouteData(uint8_t aRouterIndex,LinkQuality aLinkQualityIn,LinkQuality aLinkQualityOut,uint8_t aRouteCost)523     void SetRouteData(uint8_t aRouterIndex, LinkQuality aLinkQualityIn, LinkQuality aLinkQualityOut, uint8_t aRouteCost)
524     {
525         SetLinkQualityIn(aRouterIndex, aLinkQualityIn);
526         SetLinkQualityOut(aRouterIndex, aLinkQualityOut);
527         SetRouteCost(aRouterIndex, aRouteCost);
528     }
529 
530 private:
531     static constexpr uint8_t kLinkQualityOutOffset = 6;
532     static constexpr uint8_t kLinkQualityOutMask   = 3 << kLinkQualityOutOffset;
533     static constexpr uint8_t kLinkQualityInOffset  = 4;
534     static constexpr uint8_t kLinkQualityInMask    = 3 << kLinkQualityInOffset;
535     static constexpr uint8_t kRouteCostOffset      = 0;
536     static constexpr uint8_t kRouteCostMask        = 0xf << kRouteCostOffset;
537     static constexpr uint8_t kOddEntryOffset       = 4;
538 
SetRouteCost(uint8_t aRouterIndex,uint8_t aRouteCost)539     void SetRouteCost(uint8_t aRouterIndex, uint8_t aRouteCost)
540     {
541         if (aRouterIndex & 1)
542         {
543             mRouteData[aRouterIndex + aRouterIndex / 2 + 1] = aRouteCost;
544         }
545         else
546         {
547             mRouteData[aRouterIndex + aRouterIndex / 2] =
548                 (mRouteData[aRouterIndex + aRouterIndex / 2] & ~kRouteCostMask) |
549                 ((aRouteCost >> kOddEntryOffset) & kRouteCostMask);
550             mRouteData[aRouterIndex + aRouterIndex / 2 + 1] = static_cast<uint8_t>(
551                 (mRouteData[aRouterIndex + aRouterIndex / 2 + 1] & ~(kRouteCostMask << kOddEntryOffset)) |
552                 ((aRouteCost & kRouteCostMask) << kOddEntryOffset));
553         }
554     }
555 
SetLinkQualityIn(uint8_t aRouterIndex,uint8_t aLinkQuality)556     void SetLinkQualityIn(uint8_t aRouterIndex, uint8_t aLinkQuality)
557     {
558         int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0);
559         mRouteData[aRouterIndex + aRouterIndex / 2] =
560             (mRouteData[aRouterIndex + aRouterIndex / 2] & ~(kLinkQualityInMask >> offset)) |
561             ((aLinkQuality << (kLinkQualityInOffset - offset)) & (kLinkQualityInMask >> offset));
562     }
563 
SetLinkQualityOut(uint8_t aRouterIndex,LinkQuality aLinkQuality)564     void SetLinkQualityOut(uint8_t aRouterIndex, LinkQuality aLinkQuality)
565     {
566         int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0);
567         mRouteData[aRouterIndex + aRouterIndex / 2] =
568             (mRouteData[aRouterIndex + aRouterIndex / 2] & ~(kLinkQualityOutMask >> offset)) |
569             ((aLinkQuality << (kLinkQualityOutOffset - offset)) & (kLinkQualityOutMask >> offset));
570     }
571 
572     uint8_t     mRouterIdSequence;
573     RouterIdSet mRouterIdMask;
574     // Since we do hold 12 (compressible to 11) bits of data per router, each entry occupies 1.5 bytes,
575     // consecutively. First 4 bits are link qualities, remaining 8 bits are route cost.
576     uint8_t mRouteData[kMaxRouterId + 1 + kMaxRouterId / 2 + 1];
577 } OT_TOOL_PACKED_END;
578 
579 #endif // OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
580 
581 /**
582  * Implements Leader Data TLV generation and parsing.
583  */
584 OT_TOOL_PACKED_BEGIN
585 class LeaderDataTlv : public Tlv, public TlvInfo<Tlv::kLeaderData>
586 {
587 public:
588     /**
589      * Initializes the TLV.
590      */
Init(void)591     void Init(void)
592     {
593         SetType(kLeaderData);
594         SetLength(sizeof(*this) - sizeof(Tlv));
595     }
596 
597     /**
598      * Indicates whether or not the TLV appears to be well-formed.
599      *
600      * @retval TRUE   If the TLV appears to be well-formed.
601      * @retval FALSE  If the TLV does not appear to be well-formed.
602      */
IsValid(void) const603     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
604 
605     /**
606      * Gets the Leader Data info from TLV.
607      *
608      * @param[out] aLeaderData   A reference to output Leader Data info.
609      */
Get(LeaderData & aLeaderData) const610     void Get(LeaderData &aLeaderData) const
611     {
612         aLeaderData.SetPartitionId(BigEndian::HostSwap32(mPartitionId));
613         aLeaderData.SetWeighting(mWeighting);
614         aLeaderData.SetDataVersion(mDataVersion);
615         aLeaderData.SetStableDataVersion(mStableDataVersion);
616         aLeaderData.SetLeaderRouterId(mLeaderRouterId);
617     }
618 
619     /**
620      * Sets the Leader Data.
621      *
622      * @param[in] aLeaderData   A Leader Data.
623      */
Set(const LeaderData & aLeaderData)624     void Set(const LeaderData &aLeaderData)
625     {
626         mPartitionId       = BigEndian::HostSwap32(aLeaderData.GetPartitionId());
627         mWeighting         = aLeaderData.GetWeighting();
628         mDataVersion       = aLeaderData.GetDataVersion(NetworkData::kFullSet);
629         mStableDataVersion = aLeaderData.GetDataVersion(NetworkData::kStableSubset);
630         mLeaderRouterId    = aLeaderData.GetLeaderRouterId();
631     }
632 
633 private:
634     uint32_t mPartitionId;
635     uint8_t  mWeighting;
636     uint8_t  mDataVersion;
637     uint8_t  mStableDataVersion;
638     uint8_t  mLeaderRouterId;
639 } OT_TOOL_PACKED_END;
640 
641 /**
642  * Implements Scan Mask TLV generation and parsing.
643  */
644 class ScanMaskTlv : public UintTlvInfo<Tlv::kScanMask, uint8_t>
645 {
646 public:
647     static constexpr uint8_t kRouterFlag    = 1 << 7; ///< Scan Mask Router Flag.
648     static constexpr uint8_t kEndDeviceFlag = 1 << 6; ///< Scan Mask End Device Flag.
649 
650     /**
651      * Indicates whether or not the Router flag is set.
652      *
653      * @param[in] aMask   A scan mask value.
654      *
655      * @retval TRUE   If the Router flag is set.
656      * @retval FALSE  If the Router flag is not set.
657      */
IsRouterFlagSet(uint8_t aMask)658     static bool IsRouterFlagSet(uint8_t aMask) { return (aMask & kRouterFlag) != 0; }
659 
660     /**
661      * Indicates whether or not the End Device flag is set.
662      *
663      * @param[in] aMask   A scan mask value.
664      *
665      * @retval TRUE   If the End Device flag is set.
666      * @retval FALSE  If the End Device flag is not set.
667      */
IsEndDeviceFlagSet(uint8_t aMask)668     static bool IsEndDeviceFlagSet(uint8_t aMask) { return (aMask & kEndDeviceFlag) != 0; }
669 };
670 
671 /**
672  * Implements Connectivity TLV generation and parsing.
673  */
674 OT_TOOL_PACKED_BEGIN
675 class ConnectivityTlv : public Tlv, public TlvInfo<Tlv::kConnectivity>
676 {
677 public:
678     /**
679      * Initializes the TLV.
680      */
Init(void)681     void Init(void)
682     {
683         SetType(kConnectivity);
684         SetLength(sizeof(*this) - sizeof(Tlv));
685     }
686 
687     /**
688      * Indicates whether or not the TLV appears to be well-formed.
689      *
690      * @retval TRUE   If the TLV appears to be well-formed.
691      * @retval FALSE  If the TLV does not appear to be well-formed.
692      */
IsValid(void) const693     bool IsValid(void) const
694     {
695         return IsSedBufferingIncluded() ||
696                (GetLength() == sizeof(*this) - sizeof(Tlv) - sizeof(mSedBufferSize) - sizeof(mSedDatagramCount));
697     }
698 
699     /**
700      * Indicates whether or not the sed buffer size and datagram count are included.
701      *
702      * @retval TRUE   If the sed buffer size and datagram count are included.
703      * @retval FALSE  If the sed buffer size and datagram count are not included.
704      */
IsSedBufferingIncluded(void) const705     bool IsSedBufferingIncluded(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
706 
707     /**
708      * Returns the Parent Priority value.
709      *
710      * @returns The Parent Priority value.
711      */
712     int8_t GetParentPriority(void) const;
713 
714     /**
715      * Sets the Parent Priority value.
716      *
717      * @param[in] aParentPriority  The Parent Priority value.
718      */
719     void SetParentPriority(int8_t aParentPriority);
720 
721     /**
722      * Returns the Link Quality 3 value.
723      *
724      * @returns The Link Quality 3 value.
725      */
GetLinkQuality3(void) const726     uint8_t GetLinkQuality3(void) const { return mLinkQuality3; }
727 
728     /**
729      * Sets the Link Quality 3 value.
730      *
731      * @param[in]  aLinkQuality  The Link Quality 3 value.
732      */
SetLinkQuality3(uint8_t aLinkQuality)733     void SetLinkQuality3(uint8_t aLinkQuality) { mLinkQuality3 = aLinkQuality; }
734 
735     /**
736      * Returns the Link Quality 2 value.
737      *
738      * @returns The Link Quality 2 value.
739      */
GetLinkQuality2(void) const740     uint8_t GetLinkQuality2(void) const { return mLinkQuality2; }
741 
742     /**
743      * Sets the Link Quality 2 value.
744      *
745      * @param[in]  aLinkQuality  The Link Quality 2 value.
746      */
SetLinkQuality2(uint8_t aLinkQuality)747     void SetLinkQuality2(uint8_t aLinkQuality) { mLinkQuality2 = aLinkQuality; }
748 
749     /**
750      * Sets the Link Quality 1 value.
751      *
752      * @returns The Link Quality 1 value.
753      */
GetLinkQuality1(void) const754     uint8_t GetLinkQuality1(void) const { return mLinkQuality1; }
755 
756     /**
757      * Sets the Link Quality 1 value.
758      *
759      * @param[in]  aLinkQuality  The Link Quality 1 value.
760      */
SetLinkQuality1(uint8_t aLinkQuality)761     void SetLinkQuality1(uint8_t aLinkQuality) { mLinkQuality1 = aLinkQuality; }
762 
763     /**
764      * Increments the Link Quality N field in TLV for a given Link Quality N (1,2,3).
765      *
766      * The Link Quality N field specifies the number of neighboring router devices with which the sender shares a link
767      * of quality N.
768      *
769      * @param[in] aLinkQuality  The Link Quality N (1,2,3) field to update.
770      */
771     void IncrementLinkQuality(LinkQuality aLinkQuality);
772 
773     /**
774      * Sets the Active Routers value.
775      *
776      * @returns The Active Routers value.
777      */
GetActiveRouters(void) const778     uint8_t GetActiveRouters(void) const { return mActiveRouters; }
779 
780     /**
781      * Indicates whether or not the partition is a singleton based on Active Routers value.
782      *
783      * @retval TRUE   The partition is a singleton.
784      * @retval FALSE  The partition is not a singleton.
785      */
IsSingleton(void) const786     bool IsSingleton(void) const { return (mActiveRouters <= 1); }
787 
788     /**
789      * Sets the Active Routers value.
790      *
791      * @param[in]  aActiveRouters  The Active Routers value.
792      */
SetActiveRouters(uint8_t aActiveRouters)793     void SetActiveRouters(uint8_t aActiveRouters) { mActiveRouters = aActiveRouters; }
794 
795     /**
796      * Returns the Leader Cost value.
797      *
798      * @returns The Leader Cost value.
799      */
GetLeaderCost(void) const800     uint8_t GetLeaderCost(void) const { return mLeaderCost; }
801 
802     /**
803      * Sets the Leader Cost value.
804      *
805      * @param[in]  aCost  The Leader Cost value.
806      */
SetLeaderCost(uint8_t aCost)807     void SetLeaderCost(uint8_t aCost) { mLeaderCost = aCost; }
808 
809     /**
810      * Returns the ID Sequence value.
811      *
812      * @returns The ID Sequence value.
813      */
GetIdSequence(void) const814     uint8_t GetIdSequence(void) const { return mIdSequence; }
815 
816     /**
817      * Sets the ID Sequence value.
818      *
819      * @param[in]  aSequence  The ID Sequence value.
820      */
SetIdSequence(uint8_t aSequence)821     void SetIdSequence(uint8_t aSequence) { mIdSequence = aSequence; }
822 
823     /**
824      * Returns the SED Buffer Size value.
825      *
826      * @returns The SED Buffer Size value.
827      */
GetSedBufferSize(void) const828     uint16_t GetSedBufferSize(void) const
829     {
830         uint16_t buffersize = OPENTHREAD_CONFIG_DEFAULT_SED_BUFFER_SIZE;
831 
832         if (IsSedBufferingIncluded())
833         {
834             buffersize = BigEndian::HostSwap16(mSedBufferSize);
835         }
836         return buffersize;
837     }
838 
839     /**
840      * Sets the SED Buffer Size value.
841      *
842      * @param[in]  aSedBufferSize  The SED Buffer Size value.
843      */
SetSedBufferSize(uint16_t aSedBufferSize)844     void SetSedBufferSize(uint16_t aSedBufferSize) { mSedBufferSize = BigEndian::HostSwap16(aSedBufferSize); }
845 
846     /**
847      * Returns the SED Datagram Count value.
848      *
849      * @returns The SED Datagram Count value.
850      */
GetSedDatagramCount(void) const851     uint8_t GetSedDatagramCount(void) const
852     {
853         uint8_t count = OPENTHREAD_CONFIG_DEFAULT_SED_DATAGRAM_COUNT;
854 
855         if (IsSedBufferingIncluded())
856         {
857             count = mSedDatagramCount;
858         }
859         return count;
860     }
861 
862     /**
863      * Sets the SED Datagram Count value.
864      *
865      * @param[in]  aSedDatagramCount  The SED Datagram Count value.
866      */
SetSedDatagramCount(uint8_t aSedDatagramCount)867     void SetSedDatagramCount(uint8_t aSedDatagramCount) { mSedDatagramCount = aSedDatagramCount; }
868 
869 private:
870     static constexpr uint8_t kFlagsParentPriorityOffset = 6;
871     static constexpr uint8_t kFlagsParentPriorityMask   = (3 << kFlagsParentPriorityOffset);
872 
873     uint8_t  mFlags;
874     uint8_t  mLinkQuality3;
875     uint8_t  mLinkQuality2;
876     uint8_t  mLinkQuality1;
877     uint8_t  mLeaderCost;
878     uint8_t  mIdSequence;
879     uint8_t  mActiveRouters;
880     uint16_t mSedBufferSize;
881     uint8_t  mSedDatagramCount;
882 } OT_TOOL_PACKED_END;
883 
884 /**
885  * Specifies Status TLV status values.
886  */
887 struct StatusTlv : public UintTlvInfo<Tlv::kStatus, uint8_t>
888 {
889     /**
890      * Status values.
891      */
892     enum Status : uint8_t
893     {
894         kError = 1, ///< Error.
895     };
896 };
897 
898 /**
899  * Provides constants and methods for generation and parsing of Address Registration TLV.
900  */
901 class AddressRegistrationTlv : public TlvInfo<Tlv::kAddressRegistration>
902 {
903 public:
904     /**
905      * This constant defines the control byte to use in an uncompressed entry where the full IPv6 address is included in
906      * the TLV.
907      */
908     static constexpr uint8_t kControlByteUncompressed = 0;
909 
910     /**
911      * Returns the control byte to use in a compressed entry where the 64-prefix is replaced with a
912      * 6LoWPAN context identifier.
913      *
914      * @param[in] aContextId   The 6LoWPAN context ID.
915      *
916      * @returns The control byte associated with compressed entry with @p aContextId.
917      */
ControlByteFor(uint8_t aContextId)918     static uint8_t ControlByteFor(uint8_t aContextId) { return kCompressed | (aContextId & kContextIdMask); }
919 
920     /**
921      * Indicates whether or not an address entry is using compressed format.
922      *
923      * @param[in] aControlByte  The control byte (the first byte in the entry).
924      *
925      * @retval TRUE   If the entry uses compressed format.
926      * @retval FALSE  If the entry uses uncompressed format.
927      */
IsEntryCompressed(uint8_t aControlByte)928     static bool IsEntryCompressed(uint8_t aControlByte) { return (aControlByte & kCompressed); }
929 
930     /**
931      * Gets the context ID in a compressed entry.
932      *
933      * @param[in] aControlByte  The control byte (the first byte in the entry).
934      *
935      * @returns The 6LoWPAN context ID.
936      */
GetContextId(uint8_t aControlByte)937     static uint8_t GetContextId(uint8_t aControlByte) { return (aControlByte & kContextIdMask); }
938 
939     AddressRegistrationTlv(void) = delete;
940 
941 private:
942     static constexpr uint8_t kCompressed    = 1 << 7;
943     static constexpr uint8_t kContextIdMask = 0xf;
944 };
945 
946 /**
947  * Implements Channel TLV value format.
948  *
949  * This is used by both Channel TLV and CSL Channel TLV.
950  */
951 OT_TOOL_PACKED_BEGIN
952 class ChannelTlvValue
953 {
954 public:
955     /**
956      * Default constructor.
957      */
958     ChannelTlvValue(void) = default;
959 
960     /**
961      * Initializes the `ChannelTlvValue` with a given channel page and channel values.
962      *
963      * @param[in] aChannelPage   The channel page.
964      * @param[in] aChannel       The channel.
965      */
ChannelTlvValue(uint8_t aChannelPage,uint16_t aChannel)966     ChannelTlvValue(uint8_t aChannelPage, uint16_t aChannel)
967         : mChannelPage(aChannelPage)
968         , mChannel(BigEndian::HostSwap16(aChannel))
969     {
970     }
971 
972     /**
973      * Initializes the `ChannelTlvValue` with zero channel page and a given channel value.
974      *
975      * @param[in] aChannel       The channel.
976      */
ChannelTlvValue(uint16_t aChannel)977     ChannelTlvValue(uint16_t aChannel)
978         : ChannelTlvValue(0, aChannel)
979     {
980     }
981 
982     /**
983      * Returns the Channel Page value.
984      *
985      * @returns The Channel Page value.
986      */
GetChannelPage(void) const987     uint8_t GetChannelPage(void) const { return mChannelPage; }
988 
989     /**
990      * Sets the Channel Page value.
991      *
992      * @param[in]  aChannelPage  The Channel Page value.
993      */
SetChannelPage(uint8_t aChannelPage)994     void SetChannelPage(uint8_t aChannelPage) { mChannelPage = aChannelPage; }
995 
996     /**
997      * Returns the Channel value.
998      *
999      * @returns The Channel value.
1000      */
GetChannel(void) const1001     uint16_t GetChannel(void) const { return BigEndian::HostSwap16(mChannel); }
1002 
1003     /**
1004      * Sets the Channel value.
1005      *
1006      * @param[in]  aChannel  The Channel value.
1007      */
SetChannel(uint16_t aChannel)1008     void SetChannel(uint16_t aChannel) { mChannel = BigEndian::HostSwap16(aChannel); }
1009 
1010     /**
1011      * Sets the Channel and determines and sets the Channel Page from the given channel.
1012      *
1013      * @param[in]  aChannel  The Channel value.
1014      */
1015     void SetChannelAndPage(uint16_t aChannel);
1016 
1017     /**
1018      * Indicates whether or not the Channel and Channel Page values are valid.
1019      *
1020      * @retval TRUE   If the Channel and Channel Page values are valid.
1021      * @retval FALSE  If the Channel and Channel Page values are not valid.
1022      */
1023     bool IsValid(void) const;
1024 
1025 private:
1026     uint8_t  mChannelPage;
1027     uint16_t mChannel;
1028 } OT_TOOL_PACKED_END;
1029 
1030 /**
1031  * Defines Channel TLV constants and types.
1032  */
1033 typedef SimpleTlvInfo<Tlv::kChannel, ChannelTlvValue> ChannelTlv;
1034 
1035 /**
1036  * Defines CSL Channel TLV constants and types.
1037  */
1038 typedef SimpleTlvInfo<Tlv::kCslChannel, ChannelTlvValue> CslChannelTlv;
1039 
1040 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1041 /**
1042  * Defines Time Request TLV constants and types.
1043  */
1044 typedef TlvInfo<Tlv::kTimeRequest> TimeRequestTlv;
1045 
1046 /**
1047  * Implements Time Parameter TLV generation and parsing.
1048  */
1049 OT_TOOL_PACKED_BEGIN
1050 class TimeParameterTlv : public Tlv, public TlvInfo<Tlv::kTimeParameter>
1051 {
1052 public:
1053     /**
1054      * Initializes the TLV.
1055      */
Init(void)1056     void Init(void)
1057     {
1058         SetType(kTimeParameter);
1059         SetLength(sizeof(*this) - sizeof(Tlv));
1060     }
1061 
1062     /**
1063      * Indicates whether or not the TLV appears to be well-formed.
1064      *
1065      * @retval TRUE   If the TLV appears to be well-formed.
1066      * @retval FALSE  If the TLV does not appear to be well-formed.
1067      */
IsValid(void) const1068     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
1069 
1070     /**
1071      * Returns the time sync period.
1072      *
1073      * @returns The time sync period.
1074      */
GetTimeSyncPeriod(void) const1075     uint16_t GetTimeSyncPeriod(void) const { return BigEndian::HostSwap16(mTimeSyncPeriod); }
1076 
1077     /**
1078      * Sets the time sync period.
1079      *
1080      * @param[in]  aTimeSyncPeriod  The time sync period.
1081      */
SetTimeSyncPeriod(uint16_t aTimeSyncPeriod)1082     void SetTimeSyncPeriod(uint16_t aTimeSyncPeriod) { mTimeSyncPeriod = BigEndian::HostSwap16(aTimeSyncPeriod); }
1083 
1084     /**
1085      * Returns the XTAL accuracy threshold.
1086      *
1087      * @returns The XTAL accuracy threshold.
1088      */
GetXtalThreshold(void) const1089     uint16_t GetXtalThreshold(void) const { return BigEndian::HostSwap16(mXtalThreshold); }
1090 
1091     /**
1092      * Sets the XTAL accuracy threshold.
1093      *
1094      * @param[in]  aXTALThreshold  The XTAL accuracy threshold.
1095      */
SetXtalThreshold(uint16_t aXtalThreshold)1096     void SetXtalThreshold(uint16_t aXtalThreshold) { mXtalThreshold = BigEndian::HostSwap16(aXtalThreshold); }
1097 
1098 private:
1099     uint16_t mTimeSyncPeriod;
1100     uint16_t mXtalThreshold;
1101 } OT_TOOL_PACKED_END;
1102 
1103 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1104 
1105 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
1106 /**
1107  * Implements CSL Clock Accuracy TLV generation and parsing.
1108  */
1109 OT_TOOL_PACKED_BEGIN
1110 class CslClockAccuracyTlv : public Tlv, public TlvInfo<Tlv::kCslClockAccuracy>
1111 {
1112 public:
1113     /**
1114      * Initializes the TLV.
1115      */
Init(void)1116     void Init(void)
1117     {
1118         SetType(kCslClockAccuracy);
1119         SetLength(sizeof(*this) - sizeof(Tlv));
1120     }
1121 
1122     /**
1123      * Indicates whether or not the TLV appears to be well-formed.
1124      *
1125      * @retval TRUE   If the TLV appears to be well-formed.
1126      * @retval FALSE  If the TLV does not appear to be well-formed.
1127      */
IsValid(void) const1128     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
1129 
1130     /**
1131      * Returns the CSL Clock Accuracy value.
1132      *
1133      * @returns The CSL Clock Accuracy value.
1134      */
GetCslClockAccuracy(void) const1135     uint8_t GetCslClockAccuracy(void) const { return mCslClockAccuracy; }
1136 
1137     /**
1138      * Sets the CSL Clock Accuracy value.
1139      *
1140      * @param[in]  aCslClockAccuracy  The CSL Clock Accuracy value.
1141      */
SetCslClockAccuracy(uint8_t aCslClockAccuracy)1142     void SetCslClockAccuracy(uint8_t aCslClockAccuracy) { mCslClockAccuracy = aCslClockAccuracy; }
1143 
1144     /**
1145      * Returns the Clock Uncertainty value.
1146      *
1147      * @returns The Clock Uncertainty value.
1148      */
GetCslUncertainty(void) const1149     uint8_t GetCslUncertainty(void) const { return mCslUncertainty; }
1150 
1151     /**
1152      * Sets the CSL Uncertainty value.
1153      *
1154      * @param[in]  aCslUncertainty  The CSL Uncertainty value.
1155      */
SetCslUncertainty(uint8_t aCslUncertainty)1156     void SetCslUncertainty(uint8_t aCslUncertainty) { mCslUncertainty = aCslUncertainty; }
1157 
1158 private:
1159     uint8_t mCslClockAccuracy;
1160     uint8_t mCslUncertainty;
1161 } OT_TOOL_PACKED_END;
1162 
1163 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
1164 /**
1165  * @}
1166  */
1167 
1168 } // namespace Mle
1169 
1170 } // namespace ot
1171 
1172 #endif // MLE_TLVS_HPP_
1173