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 NETWORK_DIAGNOSTIC_TLVS_HPP_
35 #define NETWORK_DIAGNOSTIC_TLVS_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/thread.h>
40 
41 #include "common/encoding.hpp"
42 #include "common/message.hpp"
43 #include "common/tlvs.hpp"
44 #include "net/ip6_address.hpp"
45 #include "radio/radio.hpp"
46 #include "thread/mle_types.hpp"
47 
48 namespace ot {
49 
50 namespace NetworkDiagnostic {
51 
52 using ot::Encoding::BigEndian::HostSwap16;
53 using ot::Encoding::BigEndian::HostSwap32;
54 
55 /**
56  * @addtogroup core-mle-tlvs
57  *
58  * @brief
59  *   This module includes definitions for generating and processing MLE TLVs.
60  *
61  * @{
62  *
63  */
64 
65 /**
66  * This class implements MLE TLV generation and parsing.
67  *
68  */
69 OT_TOOL_PACKED_BEGIN
70 class NetworkDiagnosticTlv : public ot::Tlv
71 {
72 public:
73     /**
74      * MLE TLV Types.
75      *
76      */
77     enum Type : uint8_t
78     {
79         kExtMacAddress   = OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS,
80         kAddress16       = OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS,
81         kMode            = OT_NETWORK_DIAGNOSTIC_TLV_MODE,
82         kTimeout         = OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT,
83         kConnectivity    = OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY,
84         kRoute           = OT_NETWORK_DIAGNOSTIC_TLV_ROUTE,
85         kLeaderData      = OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA,
86         kNetworkData     = OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA,
87         kIp6AddressList  = OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST,
88         kMacCounters     = OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS,
89         kBatteryLevel    = OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL,
90         kSupplyVoltage   = OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE,
91         kChildTable      = OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE,
92         kChannelPages    = OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES,
93         kTypeList        = OT_NETWORK_DIAGNOSTIC_TLV_TYPE_LIST,
94         kMaxChildTimeout = OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT,
95     };
96 
97     /**
98      * This method returns the Type value.
99      *
100      * @returns The Type value.
101      *
102      */
GetType(void) const103     Type GetType(void) const { return static_cast<Type>(ot::Tlv::GetType()); }
104 
105     /**
106      * This method sets the Type value.
107      *
108      * @param[in]  aType  The Type value.
109      *
110      */
SetType(Type aType)111     void SetType(Type aType) { ot::Tlv::SetType(static_cast<uint8_t>(aType)); }
112 
113 } OT_TOOL_PACKED_END;
114 
115 /**
116  * This class defines Extended MAC Address TLV constants and types.
117  *
118  */
119 typedef SimpleTlvInfo<NetworkDiagnosticTlv::kExtMacAddress, Mac::ExtAddress> ExtMacAddressTlv;
120 
121 /**
122  * This class defines Address16 TLV constants and types.
123  *
124  */
125 typedef UintTlvInfo<NetworkDiagnosticTlv::kAddress16, uint16_t> Address16Tlv;
126 
127 /**
128  * This class defines Mode TLV constants and types.
129  *
130  */
131 typedef UintTlvInfo<NetworkDiagnosticTlv::kMode, uint8_t> ModeTlv;
132 
133 /**
134  * This class defines Timeout TLV constants and types.
135  *
136  */
137 typedef UintTlvInfo<NetworkDiagnosticTlv::kTimeout, uint32_t> TimeoutTlv;
138 
139 /**
140  * This class defines Battery Level TLV constants and types.
141  *
142  */
143 typedef UintTlvInfo<NetworkDiagnosticTlv::kBatteryLevel, uint8_t> BatteryLevelTlv;
144 
145 /**
146  * This class defines Supply Voltage TLV constants and types.
147  *
148  */
149 typedef UintTlvInfo<NetworkDiagnosticTlv::kSupplyVoltage, uint16_t> SupplyVoltageTlv;
150 
151 /**
152  * This class defines Max Child Timeout TLV constants and types.
153  *
154  */
155 typedef UintTlvInfo<NetworkDiagnosticTlv::kMaxChildTimeout, uint32_t> MaxChildTimeoutTlv;
156 
157 /**
158  * This class implements Connectivity TLV generation and parsing.
159  *
160  */
161 OT_TOOL_PACKED_BEGIN
162 class ConnectivityTlv : public NetworkDiagnosticTlv, public TlvInfo<NetworkDiagnosticTlv::kConnectivity>
163 {
164 public:
165     /**
166      * This method initializes the TLV.
167      *
168      */
Init(void)169     void Init(void)
170     {
171         SetType(kConnectivity);
172         SetLength(sizeof(*this) - sizeof(NetworkDiagnosticTlv));
173     }
174 
175     /**
176      * This method indicates whether or not the TLV appears to be well-formed.
177      *
178      * @retval TRUE   If the TLV appears to be well-formed.
179      * @retval FALSE  If the TLV does not appear to be well-formed.
180      *
181      */
IsValid(void) const182     bool IsValid(void) const
183     {
184         return IsSedBufferingIncluded() || (GetLength() == sizeof(*this) - sizeof(NetworkDiagnosticTlv) -
185                                                                sizeof(mSedBufferSize) - sizeof(mSedDatagramCount));
186     }
187 
188     /**
189      * This method indicates whether or not the sed buffer size and datagram count are included.
190      *
191      * @retval TRUE   If the sed buffer size and datagram count are included.
192      * @retval FALSE  If the sed buffer size and datagram count are not included.
193      *
194      */
IsSedBufferingIncluded(void) const195     bool IsSedBufferingIncluded(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
196 
197     /**
198      * This method returns the Parent Priority value.
199      *
200      * @returns The Parent Priority value.
201      *
202      */
GetParentPriority(void) const203     int8_t GetParentPriority(void) const { return (mParentPriority & kParentPriorityMask) >> kParentPriorityOffset; }
204 
205     /**
206      * This method sets the Parent Priority value.
207      *
208      * @param[in] aParentPriority  The Parent Priority value.
209      *
210      */
SetParentPriority(int8_t aParentPriority)211     void SetParentPriority(int8_t aParentPriority)
212     {
213         mParentPriority = (aParentPriority << kParentPriorityOffset) & kParentPriorityMask;
214     }
215 
216     /**
217      * This method returns the Link Quality 3 value.
218      *
219      * @returns The Link Quality 3 value.
220      *
221      */
GetLinkQuality3(void) const222     uint8_t GetLinkQuality3(void) const { return mLinkQuality3; }
223 
224     /**
225      * This method sets the Link Quality 3 value.
226      *
227      * @param[in]  aLinkQuality  The Link Quality 3 value.
228      *
229      */
SetLinkQuality3(uint8_t aLinkQuality)230     void SetLinkQuality3(uint8_t aLinkQuality) { mLinkQuality3 = aLinkQuality; }
231 
232     /**
233      * This method returns the Link Quality 2 value.
234      *
235      * @returns The Link Quality 2 value.
236      *
237      */
GetLinkQuality2(void) const238     uint8_t GetLinkQuality2(void) const { return mLinkQuality2; }
239 
240     /**
241      * This method sets the Link Quality 2 value.
242      *
243      * @param[in]  aLinkQuality  The Link Quality 2 value.
244      *
245      */
SetLinkQuality2(uint8_t aLinkQuality)246     void SetLinkQuality2(uint8_t aLinkQuality) { mLinkQuality2 = aLinkQuality; }
247 
248     /**
249      * This method sets the Link Quality 1 value.
250      *
251      * @returns The Link Quality 1 value.
252      *
253      */
GetLinkQuality1(void) const254     uint8_t GetLinkQuality1(void) const { return mLinkQuality1; }
255 
256     /**
257      * This method sets the Link Quality 1 value.
258      *
259      * @param[in]  aLinkQuality  The Link Quality 1 value.
260      *
261      */
SetLinkQuality1(uint8_t aLinkQuality)262     void SetLinkQuality1(uint8_t aLinkQuality) { mLinkQuality1 = aLinkQuality; }
263 
264     /**
265      * This method sets the Active Routers value.
266      *
267      * @returns The Active Routers value.
268      *
269      */
GetActiveRouters(void) const270     uint8_t GetActiveRouters(void) const { return mActiveRouters; }
271 
272     /**
273      * This method sets the Active Routers value.
274      *
275      * @param[in]  aActiveRouters  The Active Routers value.
276      *
277      */
SetActiveRouters(uint8_t aActiveRouters)278     void SetActiveRouters(uint8_t aActiveRouters) { mActiveRouters = aActiveRouters; }
279 
280     /**
281      * This method returns the Leader Cost value.
282      *
283      * @returns The Leader Cost value.
284      *
285      */
GetLeaderCost(void) const286     uint8_t GetLeaderCost(void) const { return mLeaderCost; }
287 
288     /**
289      * This method sets the Leader Cost value.
290      *
291      * @param[in]  aCost  The Leader Cost value.
292      *
293      */
SetLeaderCost(uint8_t aCost)294     void SetLeaderCost(uint8_t aCost) { mLeaderCost = aCost; }
295 
296     /**
297      * This method returns the ID Sequence value.
298      *
299      * @returns The ID Sequence value.
300      *
301      */
GetIdSequence(void) const302     uint8_t GetIdSequence(void) const { return mIdSequence; }
303 
304     /**
305      * This method sets the ID Sequence value.
306      *
307      * @param[in]  aSequence  The ID Sequence value.
308      *
309      */
SetIdSequence(uint8_t aSequence)310     void SetIdSequence(uint8_t aSequence) { mIdSequence = aSequence; }
311 
312     /**
313      * This method returns the SED Buffer Size value.
314      *
315      * @returns The SED Buffer Size value.
316      *
317      */
GetSedBufferSize(void) const318     uint16_t GetSedBufferSize(void) const
319     {
320         uint16_t buffersize = OPENTHREAD_CONFIG_DEFAULT_SED_BUFFER_SIZE;
321 
322         if (IsSedBufferingIncluded())
323         {
324             buffersize = HostSwap16(mSedBufferSize);
325         }
326         return buffersize;
327     }
328 
329     /**
330      * This method sets the SED Buffer Size value.
331      *
332      * @param[in]  aSedBufferSize  The SED Buffer Size value.
333      *
334      */
SetSedBufferSize(uint16_t aSedBufferSize)335     void SetSedBufferSize(uint16_t aSedBufferSize) { mSedBufferSize = HostSwap16(aSedBufferSize); }
336 
337     /**
338      * This method returns the SED Datagram Count value.
339      *
340      * @returns The SED Datagram Count value.
341      *
342      */
GetSedDatagramCount(void) const343     uint8_t GetSedDatagramCount(void) const
344     {
345         uint8_t count = OPENTHREAD_CONFIG_DEFAULT_SED_DATAGRAM_COUNT;
346 
347         if (IsSedBufferingIncluded())
348         {
349             count = mSedDatagramCount;
350         }
351         return count;
352     }
353 
354     /**
355      * This method sets the SED Datagram Count value.
356      *
357      * @param[in]  aSedDatagramCount  The SED Datagram Count value.
358      *
359      */
SetSedDatagramCount(uint8_t aSedDatagramCount)360     void SetSedDatagramCount(uint8_t aSedDatagramCount) { mSedDatagramCount = aSedDatagramCount; }
361 
362 private:
363     static constexpr uint8_t kParentPriorityOffset = 6;
364     static constexpr uint8_t kParentPriorityMask   = 3 << kParentPriorityOffset;
365 
366     uint8_t  mParentPriority;
367     uint8_t  mLinkQuality3;
368     uint8_t  mLinkQuality2;
369     uint8_t  mLinkQuality1;
370     uint8_t  mLeaderCost;
371     uint8_t  mIdSequence;
372     uint8_t  mActiveRouters;
373     uint16_t mSedBufferSize;
374     uint8_t  mSedDatagramCount;
375 } OT_TOOL_PACKED_END;
376 
377 /**
378  * This class implements Route TLV generation and parsing.
379  *
380  */
381 OT_TOOL_PACKED_BEGIN
382 class RouteTlv : public NetworkDiagnosticTlv, public TlvInfo<NetworkDiagnosticTlv::kRoute>
383 {
384 public:
385     /**
386      * This method initializes the TLV.
387      *
388      */
Init(void)389     void Init(void)
390     {
391         SetType(kRoute);
392         SetLength(sizeof(*this) - sizeof(NetworkDiagnosticTlv));
393         mRouterIdMask.Clear();
394     }
395 
396     /**
397      * This method indicates whether or not the TLV appears to be well-formed.
398      *
399      * @retval TRUE   If the TLV appears to be well-formed.
400      * @retval FALSE  If the TLV does not appear to be well-formed.
401      *
402      */
IsValid(void) const403     bool IsValid(void) const { return GetLength() >= sizeof(mRouterIdSequence) + sizeof(mRouterIdMask); }
404 
405     /**
406      * This method returns the Router ID Sequence value.
407      *
408      * @returns The Router ID Sequence value.
409      *
410      */
GetRouterIdSequence(void) const411     uint8_t GetRouterIdSequence(void) const { return mRouterIdSequence; }
412 
413     /**
414      * This method sets the Router ID Sequence value.
415      *
416      * @param[in]  aSequence  The Router ID Sequence value.
417      *
418      */
SetRouterIdSequence(uint8_t aSequence)419     void SetRouterIdSequence(uint8_t aSequence) { mRouterIdSequence = aSequence; }
420 
421     /**
422      * This method indicates whether or not a Router ID bit is set.
423      *
424      * @param[in]  aRouterId  The Router ID.
425      *
426      * @retval TRUE   If the Router ID bit is set.
427      * @retval FALSE  If the Router ID bit is not set.
428      *
429      */
IsRouterIdSet(uint8_t aRouterId) const430     bool IsRouterIdSet(uint8_t aRouterId) const { return mRouterIdMask.Contains(aRouterId); }
431 
432     /**
433      * This method sets the Router ID bit.
434      *
435      * @param[in]  aRouterId  The Router ID bit to set.
436      *
437      */
SetRouterId(uint8_t aRouterId)438     void SetRouterId(uint8_t aRouterId) { mRouterIdMask.Add(aRouterId); }
439 
440     /**
441      * This method returns the Route Data Length value.
442      *
443      * @returns The Route Data Length value.
444      *
445      */
GetRouteDataLength(void) const446     uint8_t GetRouteDataLength(void) const { return GetLength() - sizeof(mRouterIdSequence) - sizeof(mRouterIdMask); }
447 
448     /**
449      * This method sets the Route Data Length value.
450      *
451      * @param[in]  aLength  The Route Data Length value.
452      *
453      */
SetRouteDataLength(uint8_t aLength)454     void SetRouteDataLength(uint8_t aLength) { SetLength(sizeof(mRouterIdSequence) + sizeof(mRouterIdMask) + aLength); }
455 
456     /**
457      * This method returns the Route Cost value for a given Router index.
458      *
459      * @param[in]  aRouterIndex  The Router index.
460      *
461      * @returns The Route Cost value for a given Router index.
462      *
463      */
GetRouteCost(uint8_t aRouterIndex) const464     uint8_t GetRouteCost(uint8_t aRouterIndex) const { return mRouteData[aRouterIndex] & kRouteCostMask; }
465 
466     /**
467      * This method sets the Route Cost value for a given Router index.
468      *
469      * @param[in]  aRouterIndex  The Router index.
470      * @param[in]  aRouteCost    The Route Cost value.
471      *
472      */
SetRouteCost(uint8_t aRouterIndex,uint8_t aRouteCost)473     void SetRouteCost(uint8_t aRouterIndex, uint8_t aRouteCost)
474     {
475         mRouteData[aRouterIndex] = (mRouteData[aRouterIndex] & ~kRouteCostMask) | aRouteCost;
476     }
477 
478     /**
479      * This method returns the Link Quality In value for a given Router index.
480      *
481      * @param[in]  aRouterIndex  The Router index.
482      *
483      * @returns The Link Quality In value for a given Router index.
484      *
485      */
GetLinkQualityIn(uint8_t aRouterIndex) const486     uint8_t GetLinkQualityIn(uint8_t aRouterIndex) const
487     {
488         return (mRouteData[aRouterIndex] & kLinkQualityInMask) >> kLinkQualityInOffset;
489     }
490 
491     /**
492      * This method sets the Link Quality In value for a given Router index.
493      *
494      * @param[in]  aRouterIndex  The Router index.
495      * @param[in]  aLinkQuality  The Link Quality In value for a given Router index.
496      *
497      */
SetLinkQualityIn(uint8_t aRouterIndex,uint8_t aLinkQuality)498     void SetLinkQualityIn(uint8_t aRouterIndex, uint8_t aLinkQuality)
499     {
500         mRouteData[aRouterIndex] = (mRouteData[aRouterIndex] & ~kLinkQualityInMask) |
501                                    ((aLinkQuality << kLinkQualityInOffset) & kLinkQualityInMask);
502     }
503 
504     /**
505      * This method returns the Link Quality Out value for a given Router index.
506      *
507      * @param[in]  aRouterIndex  The Router index.
508      *
509      * @returns The Link Quality Out value for a given Router index.
510      *
511      */
GetLinkQualityOut(uint8_t aRouterIndex) const512     uint8_t GetLinkQualityOut(uint8_t aRouterIndex) const
513     {
514         return (mRouteData[aRouterIndex] & kLinkQualityOutMask) >> kLinkQualityOutOffset;
515     }
516 
517     /**
518      * This method sets the Link Quality Out value for a given Router index.
519      *
520      * @param[in]  aRouterIndex  The Router index.
521      * @param[in]  aLinkQuality  The Link Quality Out value for a given Router index.
522      *
523      */
SetLinkQualityOut(uint8_t aRouterIndex,uint8_t aLinkQuality)524     void SetLinkQualityOut(uint8_t aRouterIndex, uint8_t aLinkQuality)
525     {
526         mRouteData[aRouterIndex] = (mRouteData[aRouterIndex] & ~kLinkQualityOutMask) |
527                                    ((aLinkQuality << kLinkQualityOutOffset) & kLinkQualityOutMask);
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 
538     uint8_t          mRouterIdSequence;
539     Mle::RouterIdSet mRouterIdMask;
540     uint8_t          mRouteData[Mle::kMaxRouterId + 1];
541 } OT_TOOL_PACKED_END;
542 
543 /**
544  * This class implements Leader Data TLV generation and parsing.
545  *
546  */
547 OT_TOOL_PACKED_BEGIN
548 class LeaderDataTlv : public NetworkDiagnosticTlv, public TlvInfo<NetworkDiagnosticTlv::kLeaderData>
549 {
550 public:
551     /**
552      * This method initializes the TLV.
553      *
554      */
Init(void)555     void Init(void)
556     {
557         SetType(kLeaderData);
558         SetLength(sizeof(*this) - sizeof(NetworkDiagnosticTlv));
559     }
560 
561     /**
562      * This method indicates whether or not the TLV appears to be well-formed.
563      *
564      * @retval TRUE   If the TLV appears to be well-formed.
565      * @retval FALSE  If the TLV does not appear to be well-formed.
566      *
567      */
IsValid(void) const568     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(NetworkDiagnosticTlv); }
569 
570     /**
571      * This method returns the Partition ID value.
572      *
573      * @returns The Partition ID value.
574      *
575      */
GetPartitionId(void) const576     uint32_t GetPartitionId(void) const { return HostSwap32(mPartitionId); }
577 
578     /**
579      * This method sets the Partition ID value.
580      *
581      * @param[in]  aPartitionId  The Partition ID value.
582      *
583      */
SetPartitionId(uint32_t aPartitionId)584     void SetPartitionId(uint32_t aPartitionId) { mPartitionId = HostSwap32(aPartitionId); }
585 
586     /**
587      * This method returns the Weighting value.
588      *
589      * @returns The Weighting value.
590      *
591      */
GetWeighting(void) const592     uint8_t GetWeighting(void) const { return mWeighting; }
593 
594     /**
595      * This method sets the Weighting value.
596      *
597      * @param[in]  aWeighting  The Weighting value.
598      *
599      */
SetWeighting(uint8_t aWeighting)600     void SetWeighting(uint8_t aWeighting) { mWeighting = aWeighting; }
601 
602     /**
603      * This method returns the Data Version value.
604      *
605      * @returns The Data Version value.
606      *
607      */
GetDataVersion(void) const608     uint8_t GetDataVersion(void) const { return mDataVersion; }
609 
610     /**
611      * This method sets the Data Version value.
612      *
613      * @param[in]  aVersion  The Data Version value.
614      *
615      */
SetDataVersion(uint8_t aVersion)616     void SetDataVersion(uint8_t aVersion) { mDataVersion = aVersion; }
617 
618     /**
619      * This method returns the Stable Data Version value.
620      *
621      * @returns The Stable Data Version value.
622      *
623      */
GetStableDataVersion(void) const624     uint8_t GetStableDataVersion(void) const { return mStableDataVersion; }
625 
626     /**
627      * This method sets the Stable Data Version value.
628      *
629      * @param[in]  aVersion  The Stable Data Version value.
630      *
631      */
SetStableDataVersion(uint8_t aVersion)632     void SetStableDataVersion(uint8_t aVersion) { mStableDataVersion = aVersion; }
633 
634     /**
635      * This method returns the Leader Router ID value.
636      *
637      * @returns The Leader Router ID value.
638      *
639      */
GetLeaderRouterId(void) const640     uint8_t GetLeaderRouterId(void) const { return mLeaderRouterId; }
641 
642     /**
643      * This method sets the Leader Router ID value.
644      *
645      * @param[in]  aRouterId  The Leader Router ID value.
646      *
647      */
SetLeaderRouterId(uint8_t aRouterId)648     void SetLeaderRouterId(uint8_t aRouterId) { mLeaderRouterId = aRouterId; }
649 
650 private:
651     uint32_t mPartitionId;
652     uint8_t  mWeighting;
653     uint8_t  mDataVersion;
654     uint8_t  mStableDataVersion;
655     uint8_t  mLeaderRouterId;
656 } OT_TOOL_PACKED_END;
657 
658 /**
659  * This class implements Network Data TLV generation and parsing.
660  *
661  */
662 OT_TOOL_PACKED_BEGIN
663 class NetworkDataTlv : public NetworkDiagnosticTlv, public TlvInfo<NetworkDiagnosticTlv::kNetworkData>
664 {
665 public:
666     /**
667      * This method initializes the TLV.
668      *
669      */
Init(void)670     void Init(void)
671     {
672         SetType(kNetworkData);
673         SetLength(sizeof(*this) - sizeof(NetworkDiagnosticTlv));
674     }
675 
676     /**
677      * This method indicates whether or not the TLV appears to be well-formed.
678      *
679      * @retval TRUE   If the TLV appears to be well-formed.
680      * @retval FALSE  If the TLV does not appear to be well-formed.
681      *
682      */
IsValid(void) const683     bool IsValid(void) const { return GetLength() < sizeof(*this) - sizeof(NetworkDiagnosticTlv); }
684 
685     /**
686      * This method returns a pointer to the Network Data.
687      *
688      * @returns A pointer to the Network Data.
689      *
690      */
GetNetworkData(void)691     uint8_t *GetNetworkData(void) { return mNetworkData; }
692 
693     /**
694      * This method sets the Network Data.
695      *
696      * @param[in]  aNetworkData  A pointer to the Network Data.
697      *
698      */
SetNetworkData(const uint8_t * aNetworkData)699     void SetNetworkData(const uint8_t *aNetworkData) { memcpy(mNetworkData, aNetworkData, GetLength()); }
700 
701 private:
702     uint8_t mNetworkData[255];
703 } OT_TOOL_PACKED_END;
704 
705 /**
706  * This class implements IPv6 Address List TLV generation and parsing.
707  *
708  */
709 OT_TOOL_PACKED_BEGIN
710 class Ip6AddressListTlv : public NetworkDiagnosticTlv, public TlvInfo<NetworkDiagnosticTlv::kIp6AddressList>
711 {
712 public:
713     /**
714      * This method initializes the TLV.
715      *
716      */
Init(void)717     void Init(void)
718     {
719         SetType(kIp6AddressList);
720         SetLength(sizeof(*this) - sizeof(NetworkDiagnosticTlv));
721     }
722 
723     /**
724      * This method indicates whether or not the TLV appears to be well-formed.
725      *
726      * @retval TRUE   If the TLV appears to be well-formed.
727      * @retval FALSE  If the TLV does not appear to be well-formed.
728      *
729      */
IsValid(void) const730     bool IsValid(void) const { return !IsExtended() && (GetLength() % sizeof(Ip6::Address) == 0); }
731 
732     /**
733      * This method returns a pointer to the IPv6 address entry.
734      *
735      * @param[in]  aIndex  The index into the IPv6 address list.
736      *
737      * @returns A reference to the IPv6 address.
738      *
739      */
GetIp6Address(uint8_t aIndex) const740     const Ip6::Address &GetIp6Address(uint8_t aIndex) const
741     {
742         return *reinterpret_cast<const Ip6::Address *>(GetValue() + (aIndex * sizeof(Ip6::Address)));
743     }
744 
745 } OT_TOOL_PACKED_END;
746 
747 /**
748  * This class implements Mac Counters TLV generation and parsing.
749  *
750  */
751 OT_TOOL_PACKED_BEGIN
752 class MacCountersTlv : public NetworkDiagnosticTlv, public TlvInfo<NetworkDiagnosticTlv::kMacCounters>
753 {
754 public:
755     /**
756      * This method initializes the TLV.
757      *
758      */
Init(void)759     void Init(void)
760     {
761         SetType(kMacCounters);
762         SetLength(sizeof(*this) - sizeof(NetworkDiagnosticTlv));
763     }
764 
765     /**
766      * This method indicates whether or not the TLV appears to be well-formed.
767      *
768      * @retval TRUE   If the TLV appears to be well-formed.
769      * @retval FALSE  If the TLV does not appear to be well-formed.
770      *
771      */
IsValid(void) const772     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(NetworkDiagnosticTlv); }
773 
774     /**
775      * This method returns the IfInUnknownProtos counter.
776      *
777      * @returns The IfInUnknownProtos counter
778      *
779      */
GetIfInUnknownProtos(void) const780     uint32_t GetIfInUnknownProtos(void) const { return HostSwap32(mIfInUnknownProtos); }
781 
782     /**
783      * This method sets the IfInUnknownProtos counter.
784      *
785      * @param[in]  aIfInUnknownProtos The IfInUnknownProtos counter
786      *
787      */
SetIfInUnknownProtos(const uint32_t aIfInUnknownProtos)788     void SetIfInUnknownProtos(const uint32_t aIfInUnknownProtos)
789     {
790         mIfInUnknownProtos = HostSwap32(aIfInUnknownProtos);
791     }
792 
793     /**
794      * This method returns the IfInErrors counter.
795      *
796      * @returns The IfInErrors counter
797      *
798      */
GetIfInErrors(void) const799     uint32_t GetIfInErrors(void) const { return HostSwap32(mIfInErrors); }
800 
801     /**
802      * This method sets the IfInErrors counter.
803      *
804      * @param[in]  aIfInErrors The IfInErrors counter
805      *
806      */
SetIfInErrors(const uint32_t aIfInErrors)807     void SetIfInErrors(const uint32_t aIfInErrors) { mIfInErrors = HostSwap32(aIfInErrors); }
808 
809     /**
810      * This method returns the IfOutErrors counter.
811      *
812      * @returns The IfOutErrors counter
813      *
814      */
GetIfOutErrors(void) const815     uint32_t GetIfOutErrors(void) const { return HostSwap32(mIfOutErrors); }
816 
817     /**
818      * This method sets the IfOutErrors counter.
819      *
820      * @param[in]  aIfOutErrors The IfOutErrors counter.
821      *
822      */
SetIfOutErrors(const uint32_t aIfOutErrors)823     void SetIfOutErrors(const uint32_t aIfOutErrors) { mIfOutErrors = HostSwap32(aIfOutErrors); }
824 
825     /**
826      * This method returns the IfInUcastPkts counter.
827      *
828      * @returns The IfInUcastPkts counter
829      *
830      */
GetIfInUcastPkts(void) const831     uint32_t GetIfInUcastPkts(void) const { return HostSwap32(mIfInUcastPkts); }
832 
833     /**
834      * This method sets the IfInUcastPkts counter.
835      *
836      * @param[in]  aIfInUcastPkts The IfInUcastPkts counter.
837      *
838      */
SetIfInUcastPkts(const uint32_t aIfInUcastPkts)839     void SetIfInUcastPkts(const uint32_t aIfInUcastPkts) { mIfInUcastPkts = HostSwap32(aIfInUcastPkts); }
840     /**
841      * This method returns the IfInBroadcastPkts counter.
842      *
843      * @returns The IfInBroadcastPkts counter
844      *
845      */
GetIfInBroadcastPkts(void) const846     uint32_t GetIfInBroadcastPkts(void) const { return HostSwap32(mIfInBroadcastPkts); }
847 
848     /**
849      * This method sets the IfInBroadcastPkts counter.
850      *
851      * @param[in]  aIfInBroadcastPkts The IfInBroadcastPkts counter.
852      *
853      */
SetIfInBroadcastPkts(const uint32_t aIfInBroadcastPkts)854     void SetIfInBroadcastPkts(const uint32_t aIfInBroadcastPkts)
855     {
856         mIfInBroadcastPkts = HostSwap32(aIfInBroadcastPkts);
857     }
858 
859     /**
860      * This method returns the IfInDiscards counter.
861      *
862      * @returns The IfInDiscards counter
863      *
864      */
GetIfInDiscards(void) const865     uint32_t GetIfInDiscards(void) const { return HostSwap32(mIfInDiscards); }
866 
867     /**
868      * This method sets the IfInDiscards counter.
869      *
870      * @param[in]  aIfInDiscards The IfInDiscards counter.
871      *
872      */
SetIfInDiscards(const uint32_t aIfInDiscards)873     void SetIfInDiscards(const uint32_t aIfInDiscards) { mIfInDiscards = HostSwap32(aIfInDiscards); }
874 
875     /**
876      * This method returns the IfOutUcastPkts counter.
877      *
878      * @returns The IfOutUcastPkts counter
879      *
880      */
GetIfOutUcastPkts(void) const881     uint32_t GetIfOutUcastPkts(void) const { return HostSwap32(mIfOutUcastPkts); }
882 
883     /**
884      * This method sets the IfOutUcastPkts counter.
885      *
886      * @param[in]  aIfOutUcastPkts The IfOutUcastPkts counter.
887      *
888      */
SetIfOutUcastPkts(const uint32_t aIfOutUcastPkts)889     void SetIfOutUcastPkts(const uint32_t aIfOutUcastPkts) { mIfOutUcastPkts = HostSwap32(aIfOutUcastPkts); }
890 
891     /**
892      * This method returns the IfOutBroadcastPkts counter.
893      *
894      * @returns The IfOutBroadcastPkts counter
895      *
896      */
GetIfOutBroadcastPkts(void) const897     uint32_t GetIfOutBroadcastPkts(void) const { return HostSwap32(mIfOutBroadcastPkts); }
898 
899     /**
900      * This method sets the IfOutBroadcastPkts counter.
901      *
902      * @param[in]  aIfOutBroadcastPkts The IfOutBroadcastPkts counter.
903      *
904      */
SetIfOutBroadcastPkts(const uint32_t aIfOutBroadcastPkts)905     void SetIfOutBroadcastPkts(const uint32_t aIfOutBroadcastPkts)
906     {
907         mIfOutBroadcastPkts = HostSwap32(aIfOutBroadcastPkts);
908     }
909 
910     /**
911      * This method returns the IfOutDiscards counter.
912      *
913      * @returns The IfOutDiscards counter
914      *
915      */
GetIfOutDiscards(void) const916     uint32_t GetIfOutDiscards(void) const { return HostSwap32(mIfOutDiscards); }
917 
918     /**
919      * This method sets the IfOutDiscards counter.
920      *
921      * @param[in]  aIfOutDiscards The IfOutDiscards counter.
922      *
923      */
SetIfOutDiscards(const uint32_t aIfOutDiscards)924     void SetIfOutDiscards(const uint32_t aIfOutDiscards) { mIfOutDiscards = HostSwap32(aIfOutDiscards); }
925 
926 private:
927     uint32_t mIfInUnknownProtos;
928     uint32_t mIfInErrors;
929     uint32_t mIfOutErrors;
930     uint32_t mIfInUcastPkts;
931     uint32_t mIfInBroadcastPkts;
932     uint32_t mIfInDiscards;
933     uint32_t mIfOutUcastPkts;
934     uint32_t mIfOutBroadcastPkts;
935     uint32_t mIfOutDiscards;
936 } OT_TOOL_PACKED_END;
937 
938 /**
939  * This class implements Child Table Entry generation and parsing.
940  *
941  */
942 OT_TOOL_PACKED_BEGIN
943 class ChildTableEntry
944 {
945 public:
946     /**
947      * Default constructor.
948      *
949      */
ChildTableEntry(void)950     ChildTableEntry(void)
951         : mTimeoutRsvChildId(0)
952         , mMode(0)
953     {
954     }
955 
956     /**
957      * This method returns the Timeout value.
958      *
959      * @returns The Timeout value.
960      *
961      */
GetTimeout(void) const962     uint8_t GetTimeout(void) const { return (HostSwap16(mTimeoutRsvChildId) & kTimeoutMask) >> kTimeoutOffset; }
963 
964     /**
965      * This method sets the Timeout value.
966      *
967      * @param[in]  aTimeout  The Timeout value.
968      *
969      */
SetTimeout(uint8_t aTimeout)970     void SetTimeout(uint8_t aTimeout)
971     {
972         mTimeoutRsvChildId = HostSwap16((HostSwap16(mTimeoutRsvChildId) & ~kTimeoutMask) |
973                                         ((aTimeout << kTimeoutOffset) & kTimeoutMask));
974     }
975 
976     /**
977      * This method returns the Child ID value.
978      *
979      * @returns The Child ID value.
980      *
981      */
GetChildId(void) const982     uint16_t GetChildId(void) const { return HostSwap16(mTimeoutRsvChildId) & kChildIdMask; }
983 
984     /**
985      * This method sets the Child ID value.
986      *
987      * @param[in]  aChildId  The Child ID value.
988      *
989      */
SetChildId(uint16_t aChildId)990     void SetChildId(uint16_t aChildId)
991     {
992         mTimeoutRsvChildId = HostSwap16((HostSwap16(mTimeoutRsvChildId) & ~kChildIdMask) | (aChildId & kChildIdMask));
993     }
994 
995     /**
996      * This method returns the Device Mode
997      *
998      * @returns The Device Mode
999      *
1000      */
GetMode(void) const1001     Mle::DeviceMode GetMode(void) const { return Mle::DeviceMode(mMode); }
1002 
1003     /**
1004      * This method sets the Device Mode.
1005      *
1006      * @param[in]  aMode  The Device Mode.
1007      *
1008      */
SetMode(Mle::DeviceMode aMode)1009     void SetMode(Mle::DeviceMode aMode) { mMode = aMode.Get(); }
1010 
1011     /**
1012      * This method returns the Reserved value.
1013      *
1014      * @returns The Reserved value.
1015      *
1016      */
GetReserved(void) const1017     uint8_t GetReserved(void) const { return (HostSwap16(mTimeoutRsvChildId) & kReservedMask) >> kReservedOffset; }
1018 
1019     /**
1020      * This method sets the Reserved value.
1021      *
1022      * @param[in]  aReserved  The Reserved value.
1023      *
1024      */
SetReserved(uint8_t aReserved)1025     void SetReserved(uint8_t aReserved)
1026     {
1027         mTimeoutRsvChildId = HostSwap16((HostSwap16(mTimeoutRsvChildId) & ~kReservedMask) |
1028                                         ((aReserved << kReservedOffset) & kReservedMask));
1029     }
1030 
1031 private:
1032     static constexpr uint8_t  kTimeoutOffset  = 11;
1033     static constexpr uint8_t  kReservedOffset = 9;
1034     static constexpr uint16_t kTimeoutMask    = 0xf800;
1035     static constexpr uint16_t kReservedMask   = 0x0600;
1036     static constexpr uint16_t kChildIdMask    = 0x1f;
1037 
1038     uint16_t mTimeoutRsvChildId;
1039     uint8_t  mMode;
1040 } OT_TOOL_PACKED_END;
1041 
1042 /**
1043  * This class implements Child Table TLV generation and parsing.
1044  *
1045  */
1046 OT_TOOL_PACKED_BEGIN
1047 class ChildTableTlv : public NetworkDiagnosticTlv, public TlvInfo<NetworkDiagnosticTlv::kChildTable>
1048 {
1049 public:
1050     /**
1051      * This method initializes the TLV.
1052      *
1053      */
Init(void)1054     void Init(void)
1055     {
1056         SetType(kChildTable);
1057         SetLength(sizeof(*this) - sizeof(NetworkDiagnosticTlv));
1058     }
1059 
1060     /**
1061      * This method indicates whether or not the TLV appears to be well-formed.
1062      *
1063      * @retval TRUE   If the TLV appears to be well-formed.
1064      * @retval FALSE  If the TLV does not appear to be well-formed.
1065      *
1066      */
IsValid(void) const1067     bool IsValid(void) const { return (GetLength() % sizeof(ChildTableEntry)) == 0; }
1068 
1069     /**
1070      * This method returns the number of Child Table entries.
1071      *
1072      * @returns The number of Child Table entries.
1073      *
1074      */
GetNumEntries(void) const1075     uint8_t GetNumEntries(void) const { return GetLength() / sizeof(ChildTableEntry); }
1076 
1077     /**
1078      * This method returns the Child Table entry at @p aIndex.
1079      *
1080      * @param[in]  aIndex  The index into the Child Table list.
1081      *
1082      * @returns  A reference to the Child Table entry.
1083      *
1084      */
GetEntry(uint16_t aIndex)1085     ChildTableEntry &GetEntry(uint16_t aIndex)
1086     {
1087         return *reinterpret_cast<ChildTableEntry *>(GetValue() + (aIndex * sizeof(ChildTableEntry)));
1088     }
1089 
1090     /**
1091      * This method reads the Child Table entry at @p aIndex.
1092      *
1093      * @param[out]  aEntry      A reference to a ChildTableEntry.
1094      * @param[in]   aMessage    A reference to the message.
1095      * @param[in]   aOffset     The offset of the ChildTableTLV in aMessage.
1096      * @param[in]   aIndex      The index into the Child Table list.
1097      *
1098      * @retval  kErrorNotFound   No such entry is found.
1099      * @retval  kErrorNone       Successfully read the entry.
1100      *
1101      */
ReadEntry(ChildTableEntry & aEntry,const Message & aMessage,uint16_t aOffset,uint8_t aIndex) const1102     Error ReadEntry(ChildTableEntry &aEntry, const Message &aMessage, uint16_t aOffset, uint8_t aIndex) const
1103     {
1104         return ((aIndex < GetNumEntries()) &&
1105                 (aMessage.Read(aOffset + sizeof(ChildTableTlv) + (aIndex * sizeof(ChildTableEntry)), aEntry) ==
1106                  kErrorNone))
1107                    ? kErrorNone
1108                    : kErrorInvalidArgs;
1109     }
1110 
1111 } OT_TOOL_PACKED_END;
1112 
1113 /**
1114  * This class implements Channel Pages TLV generation and parsing.
1115  *
1116  */
1117 OT_TOOL_PACKED_BEGIN
1118 class ChannelPagesTlv : public NetworkDiagnosticTlv, public TlvInfo<NetworkDiagnosticTlv::kChannelPages>
1119 {
1120 public:
1121     /**
1122      * This method initializes the TLV.
1123      *
1124      */
Init(void)1125     void Init(void)
1126     {
1127         SetType(kChannelPages);
1128         SetLength(sizeof(*this) - sizeof(NetworkDiagnosticTlv));
1129     }
1130 
1131     /**
1132      * This method indicates whether or not the TLV appears to be well-formed.
1133      *
1134      * @retval TRUE   If the TLV appears to be well-formed.
1135      * @retval FALSE  If the TLV does not appear to be well-formed.
1136      *
1137      */
IsValid(void) const1138     bool IsValid(void) const
1139     {
1140         // At least one channel page must be included.
1141         return GetLength() >= 1;
1142     }
1143 
1144     /**
1145      * This method returns a pointer to the list of Channel Pages.
1146      *
1147      * @returns A pointer to the list of Channel Pages.
1148      *
1149      */
GetChannelPages(void)1150     uint8_t *GetChannelPages(void) { return mChannelPages; }
1151 
1152 private:
1153     uint8_t mChannelPages[Radio::kNumChannelPages];
1154 } OT_TOOL_PACKED_END;
1155 
1156 /**
1157  * This class implements IPv6 Address List TLV generation and parsing.
1158  *
1159  */
1160 OT_TOOL_PACKED_BEGIN
1161 class TypeListTlv : public NetworkDiagnosticTlv, public TlvInfo<NetworkDiagnosticTlv::kTypeList>
1162 {
1163 public:
1164     /**
1165      * This method initializes the TLV.
1166      *
1167      */
Init(void)1168     void Init(void)
1169     {
1170         SetType(kTypeList);
1171         SetLength(sizeof(*this) - sizeof(NetworkDiagnosticTlv));
1172     }
1173 } OT_TOOL_PACKED_END;
1174 
1175 /**
1176  * @}
1177  *
1178  */
1179 
1180 } // namespace NetworkDiagnostic
1181 
1182 } // namespace ot
1183 
1184 #endif // NETWORK_DIAGNOSTIC_TLVS_HPP_
1185