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 Network Diagnostics 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/netdiag.h>
40 #include <openthread/thread.h>
41 
42 #include "common/clearable.hpp"
43 #include "common/encoding.hpp"
44 #include "common/message.hpp"
45 #include "common/tlvs.hpp"
46 #include "net/ip6_address.hpp"
47 #include "radio/radio.hpp"
48 #include "thread/child.hpp"
49 #include "thread/link_quality.hpp"
50 #include "thread/mle_tlvs.hpp"
51 #include "thread/mle_types.hpp"
52 #include "thread/router.hpp"
53 
54 namespace ot {
55 namespace NetworkDiagnostic {
56 
57 /**
58  * Implements Network Diagnostic TLV generation and parsing.
59  */
60 OT_TOOL_PACKED_BEGIN
61 class Tlv : public ot::Tlv
62 {
63 public:
64     /**
65      * Network Diagnostic TLV Types.
66      */
67     enum Type : uint8_t
68     {
69         kExtMacAddress       = OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS,
70         kAddress16           = OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS,
71         kMode                = OT_NETWORK_DIAGNOSTIC_TLV_MODE,
72         kTimeout             = OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT,
73         kConnectivity        = OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY,
74         kRoute               = OT_NETWORK_DIAGNOSTIC_TLV_ROUTE,
75         kLeaderData          = OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA,
76         kNetworkData         = OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA,
77         kIp6AddressList      = OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST,
78         kMacCounters         = OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS,
79         kBatteryLevel        = OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL,
80         kSupplyVoltage       = OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE,
81         kChildTable          = OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE,
82         kChannelPages        = OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES,
83         kTypeList            = OT_NETWORK_DIAGNOSTIC_TLV_TYPE_LIST,
84         kMaxChildTimeout     = OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT,
85         kEui64               = OT_NETWORK_DIAGNOSTIC_TLV_EUI64,
86         kVersion             = OT_NETWORK_DIAGNOSTIC_TLV_VERSION,
87         kVendorName          = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_NAME,
88         kVendorModel         = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_MODEL,
89         kVendorSwVersion     = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_SW_VERSION,
90         kThreadStackVersion  = OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION,
91         kChild               = OT_NETWORK_DIAGNOSTIC_TLV_CHILD,
92         kChildIp6AddressList = OT_NETWORK_DIAGNOSTIC_TLV_CHILD_IP6_ADDR_LIST,
93         kRouterNeighbor      = OT_NETWORK_DIAGNOSTIC_TLV_ROUTER_NEIGHBOR,
94         kAnswer              = OT_NETWORK_DIAGNOSTIC_TLV_ANSWER,
95         kQueryId             = OT_NETWORK_DIAGNOSTIC_TLV_QUERY_ID,
96         kMleCounters         = OT_NETWORK_DIAGNOSTIC_TLV_MLE_COUNTERS,
97         kVendorAppUrl        = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_APP_URL,
98     };
99 
100     /**
101      * Maximum length of Vendor Name TLV.
102      */
103     static constexpr uint8_t kMaxVendorNameLength = OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_NAME_TLV_LENGTH;
104 
105     /**
106      * Maximum length of Vendor Model TLV.
107      */
108     static constexpr uint8_t kMaxVendorModelLength = OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_MODEL_TLV_LENGTH;
109 
110     /**
111      * Maximum length of Vendor SW Version TLV.
112      */
113     static constexpr uint8_t kMaxVendorSwVersionLength = OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_SW_VERSION_TLV_LENGTH;
114 
115     /**
116      * Maximum length of Vendor SW Version TLV.
117      */
118     static constexpr uint8_t kMaxThreadStackVersionLength = OT_NETWORK_DIAGNOSTIC_MAX_THREAD_STACK_VERSION_TLV_LENGTH;
119 
120     /**
121      * Maximum length of Vendor SW Version TLV.
122      */
123     static constexpr uint8_t kMaxVendorAppUrlLength = OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_APP_URL_TLV_LENGTH;
124 
125     /**
126      * Returns the Type value.
127      *
128      * @returns The Type value.
129      */
GetType(void) const130     Type GetType(void) const { return static_cast<Type>(ot::Tlv::GetType()); }
131 
132     /**
133      * Sets the Type value.
134      *
135      * @param[in]  aType  The Type value.
136      */
SetType(Type aType)137     void SetType(Type aType) { ot::Tlv::SetType(static_cast<uint8_t>(aType)); }
138 
139 } OT_TOOL_PACKED_END;
140 
141 /**
142  * Defines Extended MAC Address TLV constants and types.
143  */
144 typedef SimpleTlvInfo<Tlv::kExtMacAddress, Mac::ExtAddress> ExtMacAddressTlv;
145 
146 /**
147  * Defines Address16 TLV constants and types.
148  */
149 typedef UintTlvInfo<Tlv::kAddress16, uint16_t> Address16Tlv;
150 
151 /**
152  * Defines Mode TLV constants and types.
153  */
154 typedef UintTlvInfo<Tlv::kMode, uint8_t> ModeTlv;
155 
156 /**
157  * Defines Timeout TLV constants and types.
158  */
159 typedef UintTlvInfo<Tlv::kTimeout, uint32_t> TimeoutTlv;
160 
161 /**
162  * Defines Network Data TLV constants and types.
163  */
164 typedef TlvInfo<Tlv::kNetworkData> NetworkDataTlv;
165 
166 /**
167  * Defines IPv6 Address List TLV constants and types.
168  */
169 typedef TlvInfo<Tlv::kIp6AddressList> Ip6AddressListTlv;
170 
171 /**
172  * Defines Battery Level TLV constants and types.
173  */
174 typedef UintTlvInfo<Tlv::kBatteryLevel, uint8_t> BatteryLevelTlv;
175 
176 /**
177  * Defines Supply Voltage TLV constants and types.
178  */
179 typedef UintTlvInfo<Tlv::kSupplyVoltage, uint16_t> SupplyVoltageTlv;
180 
181 /**
182  * Defines Child Table TLV constants and types.
183  */
184 typedef TlvInfo<Tlv::kChildTable> ChildTableTlv;
185 
186 /**
187  * Defines Max Child Timeout TLV constants and types.
188  */
189 typedef UintTlvInfo<Tlv::kMaxChildTimeout, uint32_t> MaxChildTimeoutTlv;
190 
191 /**
192  * Defines Eui64 TLV constants and types.
193  */
194 typedef SimpleTlvInfo<Tlv::kEui64, Mac::ExtAddress> Eui64Tlv;
195 
196 /**
197  * Defines Version TLV constants and types.
198  */
199 typedef UintTlvInfo<Tlv::kVersion, uint16_t> VersionTlv;
200 
201 /**
202  * Defines Vendor Name TLV constants and types.
203  */
204 typedef StringTlvInfo<Tlv::kVendorName, Tlv::kMaxVendorNameLength> VendorNameTlv;
205 
206 /**
207  * Defines Vendor Model TLV constants and types.
208  */
209 typedef StringTlvInfo<Tlv::kVendorModel, Tlv::kMaxVendorModelLength> VendorModelTlv;
210 
211 /**
212  * Defines Vendor SW Version TLV constants and types.
213  */
214 typedef StringTlvInfo<Tlv::kVendorSwVersion, Tlv::kMaxVendorSwVersionLength> VendorSwVersionTlv;
215 
216 /**
217  * Defines Thread Stack Version TLV constants and types.
218  */
219 typedef StringTlvInfo<Tlv::kThreadStackVersion, Tlv::kMaxThreadStackVersionLength> ThreadStackVersionTlv;
220 
221 /**
222  * Defines Vendor App URL TLV constants and types.
223  */
224 typedef StringTlvInfo<Tlv::kVendorAppUrl, Tlv::kMaxVendorAppUrlLength> VendorAppUrlTlv;
225 
226 /**
227  * Defines Child IPv6 Address List TLV constants and types.
228  */
229 typedef TlvInfo<Tlv::kChildIp6AddressList> ChildIp6AddressListTlv;
230 
231 /**
232  * Defines Query ID TLV constants and types.
233  */
234 typedef UintTlvInfo<Tlv::kQueryId, uint16_t> QueryIdTlv;
235 
236 typedef otNetworkDiagConnectivity Connectivity; ///< Network Diagnostic Connectivity value.
237 
238 /**
239  * Implements Connectivity TLV generation and parsing.
240  */
241 OT_TOOL_PACKED_BEGIN
242 class ConnectivityTlv : public Mle::ConnectivityTlv
243 {
244 public:
245     static constexpr uint8_t kType = ot::NetworkDiagnostic::Tlv::kConnectivity; ///< The TLV Type value.
246 
247     /**
248      * Initializes the TLV.
249      */
Init(void)250     void Init(void)
251     {
252         Mle::ConnectivityTlv::Init();
253         ot::Tlv::SetType(kType);
254     }
255 
256     /**
257      * Retrieves the `Connectivity` value.
258      *
259      * @param[out] aConnectivity   A reference to `Connectivity` to populate.
260      */
GetConnectivity(Connectivity & aConnectivity) const261     void GetConnectivity(Connectivity &aConnectivity) const
262     {
263         aConnectivity.mParentPriority   = GetParentPriority();
264         aConnectivity.mLinkQuality3     = GetLinkQuality3();
265         aConnectivity.mLinkQuality2     = GetLinkQuality2();
266         aConnectivity.mLinkQuality1     = GetLinkQuality1();
267         aConnectivity.mLeaderCost       = GetLeaderCost();
268         aConnectivity.mIdSequence       = GetIdSequence();
269         aConnectivity.mActiveRouters    = GetActiveRouters();
270         aConnectivity.mSedBufferSize    = GetSedBufferSize();
271         aConnectivity.mSedDatagramCount = GetSedDatagramCount();
272     }
273 
274 } OT_TOOL_PACKED_END;
275 
276 /**
277  * Implements Route TLV generation and parsing.
278  */
279 OT_TOOL_PACKED_BEGIN
280 class RouteTlv : public Mle::RouteTlv
281 {
282 public:
283     static constexpr uint8_t kType = ot::NetworkDiagnostic::Tlv::kRoute; ///< The TLV Type value.
284 
285     /**
286      * Initializes the TLV.
287      */
Init(void)288     void Init(void)
289     {
290         Mle::RouteTlv::Init();
291         ot::Tlv::SetType(kType);
292     }
293 } OT_TOOL_PACKED_END;
294 
295 /**
296  * Implements Leader Data TLV generation and parsing.
297  */
298 OT_TOOL_PACKED_BEGIN
299 class LeaderDataTlv : public Mle::LeaderDataTlv
300 {
301 public:
302     static constexpr uint8_t kType = ot::NetworkDiagnostic::Tlv::kLeaderData; ///< The TLV Type value.
303 
304     /**
305      * Initializes the TLV.
306      */
Init(void)307     void Init(void)
308     {
309         Mle::LeaderDataTlv::Init();
310         ot::Tlv::SetType(kType);
311     }
312 } OT_TOOL_PACKED_END;
313 
314 /**
315  * Implements Mac Counters TLV generation and parsing.
316  */
317 OT_TOOL_PACKED_BEGIN
318 class MacCountersTlv : public Tlv, public TlvInfo<Tlv::kMacCounters>
319 {
320 public:
321     /**
322      * Initializes the TLV.
323      */
Init(void)324     void Init(void)
325     {
326         SetType(kMacCounters);
327         SetLength(sizeof(*this) - sizeof(Tlv));
328     }
329 
330     /**
331      * Indicates whether or not the TLV appears to be well-formed.
332      *
333      * @retval TRUE   If the TLV appears to be well-formed.
334      * @retval FALSE  If the TLV does not appear to be well-formed.
335      */
IsValid(void) const336     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
337 
338     /**
339      * Returns the IfInUnknownProtos counter.
340      *
341      * @returns The IfInUnknownProtos counter
342      */
GetIfInUnknownProtos(void) const343     uint32_t GetIfInUnknownProtos(void) const { return BigEndian::HostSwap32(mIfInUnknownProtos); }
344 
345     /**
346      * Sets the IfInUnknownProtos counter.
347      *
348      * @param[in]  aIfInUnknownProtos The IfInUnknownProtos counter
349      */
SetIfInUnknownProtos(const uint32_t aIfInUnknownProtos)350     void SetIfInUnknownProtos(const uint32_t aIfInUnknownProtos)
351     {
352         mIfInUnknownProtos = BigEndian::HostSwap32(aIfInUnknownProtos);
353     }
354 
355     /**
356      * Returns the IfInErrors counter.
357      *
358      * @returns The IfInErrors counter
359      */
GetIfInErrors(void) const360     uint32_t GetIfInErrors(void) const { return BigEndian::HostSwap32(mIfInErrors); }
361 
362     /**
363      * Sets the IfInErrors counter.
364      *
365      * @param[in]  aIfInErrors The IfInErrors counter
366      */
SetIfInErrors(const uint32_t aIfInErrors)367     void SetIfInErrors(const uint32_t aIfInErrors) { mIfInErrors = BigEndian::HostSwap32(aIfInErrors); }
368 
369     /**
370      * Returns the IfOutErrors counter.
371      *
372      * @returns The IfOutErrors counter
373      */
GetIfOutErrors(void) const374     uint32_t GetIfOutErrors(void) const { return BigEndian::HostSwap32(mIfOutErrors); }
375 
376     /**
377      * Sets the IfOutErrors counter.
378      *
379      * @param[in]  aIfOutErrors The IfOutErrors counter.
380      */
SetIfOutErrors(const uint32_t aIfOutErrors)381     void SetIfOutErrors(const uint32_t aIfOutErrors) { mIfOutErrors = BigEndian::HostSwap32(aIfOutErrors); }
382 
383     /**
384      * Returns the IfInUcastPkts counter.
385      *
386      * @returns The IfInUcastPkts counter
387      */
GetIfInUcastPkts(void) const388     uint32_t GetIfInUcastPkts(void) const { return BigEndian::HostSwap32(mIfInUcastPkts); }
389 
390     /**
391      * Sets the IfInUcastPkts counter.
392      *
393      * @param[in]  aIfInUcastPkts The IfInUcastPkts counter.
394      */
SetIfInUcastPkts(const uint32_t aIfInUcastPkts)395     void SetIfInUcastPkts(const uint32_t aIfInUcastPkts) { mIfInUcastPkts = BigEndian::HostSwap32(aIfInUcastPkts); }
396     /**
397      * Returns the IfInBroadcastPkts counter.
398      *
399      * @returns The IfInBroadcastPkts counter
400      */
GetIfInBroadcastPkts(void) const401     uint32_t GetIfInBroadcastPkts(void) const { return BigEndian::HostSwap32(mIfInBroadcastPkts); }
402 
403     /**
404      * Sets the IfInBroadcastPkts counter.
405      *
406      * @param[in]  aIfInBroadcastPkts The IfInBroadcastPkts counter.
407      */
SetIfInBroadcastPkts(const uint32_t aIfInBroadcastPkts)408     void SetIfInBroadcastPkts(const uint32_t aIfInBroadcastPkts)
409     {
410         mIfInBroadcastPkts = BigEndian::HostSwap32(aIfInBroadcastPkts);
411     }
412 
413     /**
414      * Returns the IfInDiscards counter.
415      *
416      * @returns The IfInDiscards counter
417      */
GetIfInDiscards(void) const418     uint32_t GetIfInDiscards(void) const { return BigEndian::HostSwap32(mIfInDiscards); }
419 
420     /**
421      * Sets the IfInDiscards counter.
422      *
423      * @param[in]  aIfInDiscards The IfInDiscards counter.
424      */
SetIfInDiscards(const uint32_t aIfInDiscards)425     void SetIfInDiscards(const uint32_t aIfInDiscards) { mIfInDiscards = BigEndian::HostSwap32(aIfInDiscards); }
426 
427     /**
428      * Returns the IfOutUcastPkts counter.
429      *
430      * @returns The IfOutUcastPkts counter
431      */
GetIfOutUcastPkts(void) const432     uint32_t GetIfOutUcastPkts(void) const { return BigEndian::HostSwap32(mIfOutUcastPkts); }
433 
434     /**
435      * Sets the IfOutUcastPkts counter.
436      *
437      * @param[in]  aIfOutUcastPkts The IfOutUcastPkts counter.
438      */
SetIfOutUcastPkts(const uint32_t aIfOutUcastPkts)439     void SetIfOutUcastPkts(const uint32_t aIfOutUcastPkts) { mIfOutUcastPkts = BigEndian::HostSwap32(aIfOutUcastPkts); }
440 
441     /**
442      * Returns the IfOutBroadcastPkts counter.
443      *
444      * @returns The IfOutBroadcastPkts counter
445      */
GetIfOutBroadcastPkts(void) const446     uint32_t GetIfOutBroadcastPkts(void) const { return BigEndian::HostSwap32(mIfOutBroadcastPkts); }
447 
448     /**
449      * Sets the IfOutBroadcastPkts counter.
450      *
451      * @param[in]  aIfOutBroadcastPkts The IfOutBroadcastPkts counter.
452      */
SetIfOutBroadcastPkts(const uint32_t aIfOutBroadcastPkts)453     void SetIfOutBroadcastPkts(const uint32_t aIfOutBroadcastPkts)
454     {
455         mIfOutBroadcastPkts = BigEndian::HostSwap32(aIfOutBroadcastPkts);
456     }
457 
458     /**
459      * Returns the IfOutDiscards counter.
460      *
461      * @returns The IfOutDiscards counter
462      */
GetIfOutDiscards(void) const463     uint32_t GetIfOutDiscards(void) const { return BigEndian::HostSwap32(mIfOutDiscards); }
464 
465     /**
466      * Sets the IfOutDiscards counter.
467      *
468      * @param[in]  aIfOutDiscards The IfOutDiscards counter.
469      */
SetIfOutDiscards(const uint32_t aIfOutDiscards)470     void SetIfOutDiscards(const uint32_t aIfOutDiscards) { mIfOutDiscards = BigEndian::HostSwap32(aIfOutDiscards); }
471 
472 private:
473     uint32_t mIfInUnknownProtos;
474     uint32_t mIfInErrors;
475     uint32_t mIfOutErrors;
476     uint32_t mIfInUcastPkts;
477     uint32_t mIfInBroadcastPkts;
478     uint32_t mIfInDiscards;
479     uint32_t mIfOutUcastPkts;
480     uint32_t mIfOutBroadcastPkts;
481     uint32_t mIfOutDiscards;
482 } OT_TOOL_PACKED_END;
483 
484 /**
485  * Implements Child Table Entry generation and parsing.
486  */
487 OT_TOOL_PACKED_BEGIN
488 class ChildTableEntry : public Clearable<ChildTableEntry>
489 {
490 public:
491     /**
492      * Returns the Timeout value.
493      *
494      * @returns The Timeout value.
495      */
GetTimeout(void) const496     uint8_t GetTimeout(void) const { return (GetTimeoutChildId() & kTimeoutMask) >> kTimeoutOffset; }
497 
498     /**
499      * Sets the Timeout value.
500      *
501      * @param[in]  aTimeout  The Timeout value.
502      */
SetTimeout(uint8_t aTimeout)503     void SetTimeout(uint8_t aTimeout)
504     {
505         SetTimeoutChildId((GetTimeoutChildId() & ~kTimeoutMask) | ((aTimeout << kTimeoutOffset) & kTimeoutMask));
506     }
507 
508     /**
509      * The Link Quality value.
510      *
511      * @returns The Link Quality value.
512      */
GetLinkQuality(void) const513     LinkQuality GetLinkQuality(void) const
514     {
515         return static_cast<LinkQuality>((GetTimeoutChildId() & kLqiMask) >> kLqiOffset);
516     }
517 
518     /**
519      * Set the Link Quality value.
520      *
521      * @param[in] aLinkQuality  The Link Quality value.
522      */
SetLinkQuality(LinkQuality aLinkQuality)523     void SetLinkQuality(LinkQuality aLinkQuality)
524     {
525         SetTimeoutChildId((GetTimeoutChildId() & ~kLqiMask) | ((aLinkQuality << kLqiOffset) & kLqiMask));
526     }
527 
528     /**
529      * Returns the Child ID value.
530      *
531      * @returns The Child ID value.
532      */
GetChildId(void) const533     uint16_t GetChildId(void) const { return (GetTimeoutChildId() & kChildIdMask) >> kChildIdOffset; }
534 
535     /**
536      * Sets the Child ID value.
537      *
538      * @param[in]  aChildId  The Child ID value.
539      */
SetChildId(uint16_t aChildId)540     void SetChildId(uint16_t aChildId)
541     {
542         SetTimeoutChildId((GetTimeoutChildId() & ~kChildIdMask) | ((aChildId << kChildIdOffset) & kChildIdMask));
543     }
544 
545     /**
546      * Returns the Device Mode
547      *
548      * @returns The Device Mode
549      */
GetMode(void) const550     Mle::DeviceMode GetMode(void) const { return Mle::DeviceMode(mMode); }
551 
552     /**
553      * Sets the Device Mode.
554      *
555      * @param[in]  aMode  The Device Mode.
556      */
SetMode(Mle::DeviceMode aMode)557     void SetMode(Mle::DeviceMode aMode) { mMode = aMode.Get(); }
558 
559 private:
560     //             1                   0
561     //   5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
562     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
563     //  | Timeout |LQI|     Child ID    |
564     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
565 
566     static constexpr uint8_t  kTimeoutOffset = 11;
567     static constexpr uint8_t  kLqiOffset     = 9;
568     static constexpr uint8_t  kChildIdOffset = 0;
569     static constexpr uint16_t kTimeoutMask   = 0x1f << kTimeoutOffset;
570     static constexpr uint16_t kLqiMask       = 0x3 << kLqiOffset;
571     static constexpr uint16_t kChildIdMask   = 0x1ff << kChildIdOffset;
572 
GetTimeoutChildId(void) const573     uint16_t GetTimeoutChildId(void) const { return BigEndian::HostSwap16(mTimeoutChildId); }
SetTimeoutChildId(uint16_t aTimeoutChildIf)574     void     SetTimeoutChildId(uint16_t aTimeoutChildIf) { mTimeoutChildId = BigEndian::HostSwap16(aTimeoutChildIf); }
575 
576     uint16_t mTimeoutChildId;
577     uint8_t  mMode;
578 } OT_TOOL_PACKED_END;
579 
580 /**
581  * Implements Channel Pages TLV generation and parsing.
582  */
583 OT_TOOL_PACKED_BEGIN
584 class ChannelPagesTlv : public Tlv, public TlvInfo<Tlv::kChannelPages>
585 {
586 public:
587     /**
588      * Initializes the TLV.
589      */
Init(void)590     void Init(void)
591     {
592         SetType(kChannelPages);
593         SetLength(sizeof(*this) - sizeof(Tlv));
594     }
595 
596     /**
597      * Indicates whether or not the TLV appears to be well-formed.
598      *
599      * @retval TRUE   If the TLV appears to be well-formed.
600      * @retval FALSE  If the TLV does not appear to be well-formed.
601      */
IsValid(void) const602     bool IsValid(void) const
603     {
604         // At least one channel page must be included.
605         return GetLength() >= 1;
606     }
607 
608     /**
609      * Returns a pointer to the list of Channel Pages.
610      *
611      * @returns A pointer to the list of Channel Pages.
612      */
GetChannelPages(void)613     uint8_t *GetChannelPages(void) { return mChannelPages; }
614 
615 private:
616     uint8_t mChannelPages[Radio::kNumChannelPages];
617 } OT_TOOL_PACKED_END;
618 
619 /**
620  * Implements IPv6 Address List TLV generation and parsing.
621  */
622 OT_TOOL_PACKED_BEGIN
623 class TypeListTlv : public Tlv, public TlvInfo<Tlv::kTypeList>
624 {
625 public:
626     /**
627      * Initializes the TLV.
628      */
Init(void)629     void Init(void)
630     {
631         SetType(kTypeList);
632         SetLength(sizeof(*this) - sizeof(Tlv));
633     }
634 } OT_TOOL_PACKED_END;
635 
636 #if OPENTHREAD_FTD
637 
638 /**
639  * Implements Child TLV generation and parsing.
640  */
641 OT_TOOL_PACKED_BEGIN
642 class ChildTlv : public Tlv, public TlvInfo<Tlv::kChild>, public Clearable<ChildTlv>
643 {
644 public:
645     static constexpr uint8_t kFlagsRxOnWhenIdle = 1 << 7; ///< Device mode - Rx-on when idle.
646     static constexpr uint8_t kFlagsFtd          = 1 << 6; ///< Device mode - Full Thread Device (FTD).
647     static constexpr uint8_t kFlagsFullNetdta   = 1 << 5; ///< Device mode - Full Network Data.
648     static constexpr uint8_t kFlagsCslSync      = 1 << 4; ///< Is CSL capable and CSL synchronized.
649     static constexpr uint8_t kFlagsTrackErrRate = 1 << 3; ///< Supports tracking error rates.
650 
651     /**
652      * Initializes the TLV using information from a given `Child`.
653      *
654      * @param[in] aChild   The child to initialize the TLV from.
655      */
656     void InitFrom(const Child &aChild);
657 
658     /**
659      * Initializes the TLV as empty (zero length).
660      */
InitAsEmpty(void)661     void InitAsEmpty(void)
662     {
663         SetType(kChild);
664         SetLength(0);
665     }
666 
667     /**
668      * Returns the Flags field (`kFlags*` constants define bits in flags).
669      *
670      * @returns The Flags field.
671      */
GetFlags(void) const672     uint8_t GetFlags(void) const { return mFlags; }
673 
674     /**
675      * Returns the RLOC16 field.
676      *
677      * @returns The RLOC16 of the child.
678      */
GetRloc16(void) const679     uint16_t GetRloc16(void) const { return BigEndian::HostSwap16(mRloc16); }
680 
681     /**
682      * Returns the Extended Address.
683      *
684      * @returns The Extended Address of the child.
685      */
GetExtAddress(void) const686     const Mac::ExtAddress &GetExtAddress(void) const { return mExtAddress; }
687 
688     /**
689      * Returns the Version field.
690      *
691      * @returns The Version of the child.
692      */
GetVersion(void) const693     uint16_t GetVersion(void) const { return BigEndian::HostSwap16(mVersion); }
694 
695     /**
696      * Returns the Timeout field
697      *
698      * @returns The Timeout value in seconds.
699      */
GetTimeout(void) const700     uint32_t GetTimeout(void) const { return BigEndian::HostSwap32(mTimeout); }
701 
702     /**
703      * Returns the Age field.
704      *
705      * @returns The Age field (seconds since last heard from the child).
706      */
GetAge(void) const707     uint32_t GetAge(void) const { return BigEndian::HostSwap32(mAge); }
708 
709     /**
710      * Returns the Connection Time field.
711      *
712      * @returns The Connection Time field (seconds since attach).
713      */
GetConnectionTime(void) const714     uint32_t GetConnectionTime(void) const { return BigEndian::HostSwap32(mConnectionTime); }
715 
716     /**
717      * Returns the Supervision Interval field
718      *
719      * @returns The Supervision Interval in seconds. Zero indicates not used.
720      */
GetSupervisionInterval(void) const721     uint16_t GetSupervisionInterval(void) const { return BigEndian::HostSwap16(mSupervisionInterval); }
722 
723     /**
724      * Returns the Link Margin field.
725      *
726      * @returns The Link Margin in dB.
727      */
GetLinkMargin(void) const728     uint8_t GetLinkMargin(void) const { return mLinkMargin; }
729 
730     /**
731      * Returns the Average RSSI field.
732      *
733      * @returns The Average RSSI in dBm. 127 if not available or unknown.
734      */
GetAverageRssi(void) const735     int8_t GetAverageRssi(void) const { return mAverageRssi; }
736 
737     /**
738      * Returns the Last RSSI field (RSSI of last received frame from child).
739      *
740      * @returns The Last RSSI field in dBm. 127 if not available or unknown.
741      */
GetLastRssi(void) const742     int8_t GetLastRssi(void) const { return mLastRssi; }
743 
744     /**
745      * Returns the Frame Error Rate field.
746      *
747      * `kFlagsTrackErrRate` from `GetFlags()` indicates whether or not the implementation supports tracking of error
748      * rates and whether or not the value in this field is valid.
749      *
750      * @returns The Frame Error Rate (0x0000->0%, 0xffff->100%).
751      */
GetFrameErrorRate(void) const752     uint16_t GetFrameErrorRate(void) const { return BigEndian::HostSwap16(mFrameErrorRate); }
753 
754     /**
755      * Returns the Message Error Rate field.
756      *
757      * `kFlagsTrackErrRate` from `GetFlags()` indicates whether or not the implementation supports tracking of error
758      * rates and whether or not the value in this field is valid.
759      *
760      * @returns The Message Error Rate (0x0000->0%, 0xffff->100%).
761      */
GetMessageErrorRate(void) const762     uint16_t GetMessageErrorRate(void) const { return BigEndian::HostSwap16(mMessageErrorRate); }
763 
764     /**
765      * Returns the Queued Message Count field.
766      *
767      * @returns The Queued Message Count (number of queued messages for indirect tx to child).
768      */
GetQueuedMessageCount(void) const769     uint16_t GetQueuedMessageCount(void) const { return BigEndian::HostSwap16(mQueuedMessageCount); }
770 
771     /**
772      * Returns the CSL Period in unit of 10 symbols.
773      *
774      * @returns The CSL Period in unit of 10-symbols-time. Zero if CSL is not supported.
775      */
GetCslPeriod(void) const776     uint16_t GetCslPeriod(void) const { return BigEndian::HostSwap16(mCslPeriod); }
777 
778     /**
779      * Returns the CSL Timeout in seconds.
780      *
781      * @returns The CSL Timeout in seconds. Zero if unknown on parent of if CSL Is not supported.
782      */
GetCslTimeout(void) const783     uint32_t GetCslTimeout(void) const { return BigEndian::HostSwap32(mCslTimeout); }
784 
785     /**
786      * Returns the CSL Channel.
787      *
788      * @returns The CSL channel.
789      */
GetCslChannel(void) const790     uint8_t GetCslChannel(void) const { return mCslChannel; }
791 
792 private:
793     uint8_t         mFlags;               // Flags (`kFlags*` constants).
794     uint16_t        mRloc16;              // RLOC16.
795     Mac::ExtAddress mExtAddress;          // Extended Address.
796     uint16_t        mVersion;             // Version.
797     uint32_t        mTimeout;             // Timeout in seconds.
798     uint32_t        mAge;                 // Seconds since last heard from the child.
799     uint32_t        mConnectionTime;      // Seconds since attach.
800     uint16_t        mSupervisionInterval; // Supervision interval in seconds. Zero to indicate not used.
801     uint8_t         mLinkMargin;          // Link margin in dB.
802     int8_t          mAverageRssi;         // Average RSSI. 127 if not available or unknown
803     int8_t          mLastRssi;            // RSSI of last received frame. 127 if not available or unknown.
804     uint16_t        mFrameErrorRate;      // Frame error rate (0x0000->0%, 0xffff->100%).
805     uint16_t        mMessageErrorRate;    // (IPv6) msg error rate (0x0000->0%, 0xffff->100%)
806     uint16_t        mQueuedMessageCount;  // Number of queued messages for indirect tx to child.
807     uint16_t        mCslPeriod;           // CSL Period in unit of 10 symbols.
808     uint32_t        mCslTimeout;          // CSL Timeout in seconds.
809     uint8_t         mCslChannel;          // CSL channel.
810 } OT_TOOL_PACKED_END;
811 
812 /**
813  * Implements Child IPv6 Address List Value generation and parsing.
814  *
815  * This TLV can use extended or normal format depending on the number of IPv6 addresses.
816  */
817 OT_TOOL_PACKED_BEGIN
818 class ChildIp6AddressListTlvValue
819 {
820 public:
821     /**
822      * Returns the RLOC16 of the child.
823      *
824      * @returns The RLOC16 of the child.
825      */
GetRloc16(void) const826     uint16_t GetRloc16(void) const { return BigEndian::HostSwap16(mRloc16); }
827 
828     /**
829      * Sets the RLOC16.
830      *
831      * @param[in] aRloc16   The RLOC16 value.
832      */
SetRloc16(uint16_t aRloc16)833     void SetRloc16(uint16_t aRloc16) { mRloc16 = BigEndian::HostSwap16(aRloc16); }
834 
835 private:
836     uint16_t mRloc16;
837     // Followed by zero or more IPv6 address(es).
838 
839 } OT_TOOL_PACKED_END;
840 
841 /**
842  * Implements Router Neighbor TLV generation and parsing.
843  */
844 OT_TOOL_PACKED_BEGIN
845 class RouterNeighborTlv : public Tlv, public TlvInfo<Tlv::kRouterNeighbor>, public Clearable<RouterNeighborTlv>
846 {
847 public:
848     static constexpr uint8_t kFlagsTrackErrRate = 1 << 7; ///< Supports tracking error rates.
849 
850     /**
851      * Initializes the TLV using information from a given `Router`.
852      *
853      * @param[in] aRouter   The router to initialize the TLV from.
854      */
855     void InitFrom(const Router &aRouter);
856 
857     /**
858      * Initializes the TLV as empty (zero length).
859      */
InitAsEmpty(void)860     void InitAsEmpty(void)
861     {
862         SetType(kRouterNeighbor);
863         SetLength(0);
864     }
865 
866     /**
867      * Returns the Flags field (`kFlags*` constants define bits in flags).
868      *
869      * @returns The Flags field.
870      */
GetFlags(void) const871     uint8_t GetFlags(void) const { return mFlags; }
872 
873     /**
874      * Returns the RLOC16 field.
875      *
876      * @returns The RLOC16 of the router.
877      */
GetRloc16(void) const878     uint16_t GetRloc16(void) const { return BigEndian::HostSwap16(mRloc16); }
879 
880     /**
881      * Returns the Extended Address.
882      *
883      * @returns The Extended Address of the router.
884      */
GetExtAddress(void) const885     const Mac::ExtAddress &GetExtAddress(void) const { return mExtAddress; }
886 
887     /**
888      * Returns the Version field.
889      *
890      * @returns The Version of the router.
891      */
GetVersion(void) const892     uint16_t GetVersion(void) const { return BigEndian::HostSwap16(mVersion); }
893 
894     /**
895      * Returns the Connection Time field.
896      *
897      * @returns The Connection Time field (seconds since link establishment).
898      */
GetConnectionTime(void) const899     uint32_t GetConnectionTime(void) const { return BigEndian::HostSwap32(mConnectionTime); }
900 
901     /**
902      * Returns the Link Margin field.
903      *
904      * @returns The Link Margin in dB.
905      */
GetLinkMargin(void) const906     uint8_t GetLinkMargin(void) const { return mLinkMargin; }
907 
908     /**
909      * Returns the Average RSSI field.
910      *
911      * @returns The Average RSSI in dBm. 127 if not available or unknown.
912      */
GetAverageRssi(void) const913     int8_t GetAverageRssi(void) const { return mAverageRssi; }
914 
915     /**
916      * Returns the Last RSSI field (RSSI of last received frame from router).
917      *
918      * @returns The Last RSSI field in dBm. 127 if not available or unknown.
919      */
GetLastRssi(void) const920     int8_t GetLastRssi(void) const { return mLastRssi; }
921 
922     /**
923      * Returns the Frame Error Rate field.
924      *
925      * `kFlagsTrackErrRate` from `GetFlags()` indicates whether or not the implementation supports tracking of error
926      * rates and whether or not the value in this field is valid.
927      *
928      * @returns The Frame Error Rate (0x0000->0%, 0xffff->100%).
929      */
GetFrameErrorRate(void) const930     uint16_t GetFrameErrorRate(void) const { return BigEndian::HostSwap16(mFrameErrorRate); }
931 
932     /**
933      * Returns the Message Error Rate field.
934      *
935      * `kFlagsTrackErrRate` from `GetFlags()` indicates whether or not the implementation supports tracking of error
936      * rates and whether or not the value in this field is valid.
937      *
938      * @returns The Message Error Rate (0x0000->0%, 0xffff->100%).
939      */
GetMessageErrorRate(void) const940     uint16_t GetMessageErrorRate(void) const { return BigEndian::HostSwap16(mMessageErrorRate); }
941 
942 private:
943     uint8_t         mFlags;            // Flags (`kFlags*` constants).
944     uint16_t        mRloc16;           // RLOC16.
945     Mac::ExtAddress mExtAddress;       // Extended Address.
946     uint16_t        mVersion;          // Version.
947     uint32_t        mConnectionTime;   // Seconds since link establishment.
948     uint8_t         mLinkMargin;       // Link Margin.
949     int8_t          mAverageRssi;      // Average RSSI. 127 if not available or unknown
950     int8_t          mLastRssi;         // RSSI of last received frame. 127 if not available or unknown.
951     uint16_t        mFrameErrorRate;   // Frame error rate (0x0000->0%, 0xffff->100%).
952     uint16_t        mMessageErrorRate; // (IPv6) msg error rate (0x0000->0%, 0xffff->100%)
953 } OT_TOOL_PACKED_END;
954 
955 #endif // OPENTHREAD_FTD
956 
957 /**
958  * Implements Answer TLV generation and parsing.
959  */
960 OT_TOOL_PACKED_BEGIN
961 class AnswerTlv : public Tlv, public TlvInfo<Tlv::kAnswer>
962 {
963 public:
964     /**
965      * Initializes the TLV.
966      *
967      * @param[in] aIndex   The index value.
968      * @param[in] aIsLast  The "IsLast" flag value.
969      */
970     void Init(uint16_t aIndex, bool aIsLast);
971 
972     /**
973      * Indicates whether or not the "IsLast" flag is set
974      *
975      * @retval TRUE   "IsLast" flag si set (this is the last answer for this query).
976      * @retval FALSE  "IsLast" flag is not set (more answer messages are expected for this query).
977      */
IsLast(void) const978     bool IsLast(void) const { return GetFlagsIndex() & kIsLastFlag; }
979 
980     /**
981      * Gets the index.
982      *
983      * @returns The index.
984      */
GetIndex(void) const985     uint16_t GetIndex(void) const { return GetFlagsIndex() & kIndexMask; }
986 
987 private:
988     static constexpr uint16_t kIsLastFlag = 1 << 15;
989     static constexpr uint16_t kIndexMask  = 0x7f;
990 
GetFlagsIndex(void) const991     uint16_t GetFlagsIndex(void) const { return BigEndian::HostSwap16(mFlagsIndex); }
SetFlagsIndex(uint16_t aFlagsIndex)992     void     SetFlagsIndex(uint16_t aFlagsIndex) { mFlagsIndex = BigEndian::HostSwap16(aFlagsIndex); }
993 
994     uint16_t mFlagsIndex;
995 } OT_TOOL_PACKED_END;
996 
997 /**
998  * Represents the MLE Counters.
999  */
1000 typedef otNetworkDiagMleCounters MleCounters;
1001 
1002 /**
1003  * Implements MLE Counters TLV generation and parsing.
1004  */
1005 OT_TOOL_PACKED_BEGIN
1006 class MleCountersTlv : public Tlv, public TlvInfo<Tlv::kMleCounters>
1007 {
1008 public:
1009     /**
1010      * Initializes the TLV.
1011      *
1012      * @param[in] aMleCounters    The MLE counters to initialize the TLV with.
1013      */
1014     void Init(const Mle::Counters &aMleCounters);
1015 
1016     /**
1017      * Indicates whether or not the TLV appears to be well-formed.
1018      *
1019      * @retval TRUE   If the TLV appears to be well-formed.
1020      * @retval FALSE  If the TLV does not appear to be well-formed.
1021      */
IsValid(void) const1022     bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
1023 
1024     /**
1025      *
1026      * Reads the counters from TLV.
1027      *
1028      * @param[out] aDiagMleCounters   A reference to `NetworkDiagnostic::MleCounters` to populate.
1029      */
1030     void Read(MleCounters &aDiagMleCounters) const;
1031 
1032 private:
1033     uint16_t mDisabledRole;                  // Number of times device entered disabled role.
1034     uint16_t mDetachedRole;                  // Number of times device entered detached role.
1035     uint16_t mChildRole;                     // Number of times device entered child role.
1036     uint16_t mRouterRole;                    // Number of times device entered router role.
1037     uint16_t mLeaderRole;                    // Number of times device entered leader role.
1038     uint16_t mAttachAttempts;                // Number of attach attempts while device was detached.
1039     uint16_t mPartitionIdChanges;            // Number of changes to partition ID.
1040     uint16_t mBetterPartitionAttachAttempts; // Number of attempts to attach to a better partition.
1041     uint16_t mParentChanges;                 // Number of time device changed its parent.
1042     uint64_t mTrackedTime;                   // Milliseconds tracked by next counters.
1043     uint64_t mDisabledTime;                  // Milliseconds device has been in disabled role.
1044     uint64_t mDetachedTime;                  // Milliseconds device has been in detached role.
1045     uint64_t mChildTime;                     // Milliseconds device has been in child role.
1046     uint64_t mRouterTime;                    // Milliseconds device has been in router role.
1047     uint64_t mLeaderTime;                    // Milliseconds device has been in leader role.
1048 } OT_TOOL_PACKED_END;
1049 
1050 } // namespace NetworkDiagnostic
1051 } // namespace ot
1052 
1053 #endif // NETWORK_DIAGNOSTIC_TLVS_HPP_
1054