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