1 /*
2  *  Copyright (c) 2023, 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 implements methods for generating and processing Network Diagnostics TLVs.
32  */
33 
34 #include "network_diagnostic_tlvs.hpp"
35 
36 #include "common/time.hpp"
37 
38 namespace ot {
39 namespace NetworkDiagnostic {
40 
41 #if OPENTHREAD_FTD
42 
InitFrom(const Child & aChild)43 void ChildTlv::InitFrom(const Child &aChild)
44 {
45     Clear();
46 
47     SetType(kChild);
48     SetLength(sizeof(*this) - sizeof(Tlv));
49 
50     mFlags |= aChild.IsRxOnWhenIdle() ? kFlagsRxOnWhenIdle : 0;
51     mFlags |= aChild.IsFullThreadDevice() ? kFlagsFtd : 0;
52     mFlags |= (aChild.GetNetworkDataType() == NetworkData::kFullSet) ? kFlagsFullNetdta : 0;
53     mFlags |= kFlagsTrackErrRate;
54 
55     mRloc16              = BigEndian::HostSwap16(aChild.GetRloc16());
56     mExtAddress          = aChild.GetExtAddress();
57     mVersion             = BigEndian::HostSwap16(aChild.GetVersion());
58     mTimeout             = BigEndian::HostSwap32(aChild.GetTimeout());
59     mAge                 = BigEndian::HostSwap32(Time::MsecToSec(TimerMilli::GetNow() - aChild.GetLastHeard()));
60     mConnectionTime      = BigEndian::HostSwap32(aChild.GetConnectionTime());
61     mSupervisionInterval = aChild.IsRxOnWhenIdle() ? 0 : BigEndian::HostSwap16(aChild.GetSupervisionInterval());
62     mLinkMargin          = aChild.GetLinkInfo().GetLinkMargin();
63     mAverageRssi         = aChild.GetLinkInfo().GetAverageRss();
64     mLastRssi            = aChild.GetLinkInfo().GetLastRss();
65     mFrameErrorRate      = BigEndian::HostSwap16(aChild.GetLinkInfo().GetFrameErrorRate());
66     mMessageErrorRate    = BigEndian::HostSwap16(aChild.GetLinkInfo().GetMessageErrorRate());
67     mQueuedMessageCount  = BigEndian::HostSwap16(aChild.GetIndirectMessageCount());
68 
69 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
70     mFlags |= aChild.IsCslSynchronized() ? kFlagsCslSync : 0;
71     mCslPeriod  = BigEndian::HostSwap16(aChild.GetCslPeriod());
72     mCslTimeout = BigEndian::HostSwap32(aChild.GetCslTimeout());
73     mCslChannel = aChild.GetCslChannel();
74 #endif
75 }
76 
InitFrom(const Router & aRouter)77 void RouterNeighborTlv::InitFrom(const Router &aRouter)
78 {
79     Clear();
80 
81     SetType(kRouterNeighbor);
82     SetLength(sizeof(*this) - sizeof(Tlv));
83 
84     mFlags |= kFlagsTrackErrRate;
85     mRloc16           = BigEndian::HostSwap16(aRouter.GetRloc16());
86     mExtAddress       = aRouter.GetExtAddress();
87     mVersion          = BigEndian::HostSwap16(aRouter.GetVersion());
88     mConnectionTime   = BigEndian::HostSwap32(aRouter.GetConnectionTime());
89     mLinkMargin       = aRouter.GetLinkInfo().GetLinkMargin();
90     mAverageRssi      = aRouter.GetLinkInfo().GetAverageRss();
91     mLastRssi         = aRouter.GetLinkInfo().GetLastRss();
92     mFrameErrorRate   = BigEndian::HostSwap16(aRouter.GetLinkInfo().GetFrameErrorRate());
93     mMessageErrorRate = BigEndian::HostSwap16(aRouter.GetLinkInfo().GetMessageErrorRate());
94 }
95 
96 #endif // OPENTHREAD_FTD
97 
Init(uint16_t aIndex,bool aIsLast)98 void AnswerTlv::Init(uint16_t aIndex, bool aIsLast)
99 {
100     SetType(kAnswer);
101     SetLength(sizeof(*this) - sizeof(Tlv));
102 
103     SetFlagsIndex((aIndex & kIndexMask) | (aIsLast ? kIsLastFlag : 0));
104 }
105 
Init(const Mle::Counters & aMleCounters)106 void MleCountersTlv::Init(const Mle::Counters &aMleCounters)
107 {
108     SetType(kMleCounters);
109     SetLength(sizeof(*this) - sizeof(Tlv));
110 
111     mDisabledRole                  = BigEndian::HostSwap16(aMleCounters.mDisabledRole);
112     mDetachedRole                  = BigEndian::HostSwap16(aMleCounters.mDetachedRole);
113     mChildRole                     = BigEndian::HostSwap16(aMleCounters.mChildRole);
114     mRouterRole                    = BigEndian::HostSwap16(aMleCounters.mRouterRole);
115     mLeaderRole                    = BigEndian::HostSwap16(aMleCounters.mLeaderRole);
116     mAttachAttempts                = BigEndian::HostSwap16(aMleCounters.mAttachAttempts);
117     mPartitionIdChanges            = BigEndian::HostSwap16(aMleCounters.mPartitionIdChanges);
118     mBetterPartitionAttachAttempts = BigEndian::HostSwap16(aMleCounters.mBetterPartitionAttachAttempts);
119     mParentChanges                 = BigEndian::HostSwap16(aMleCounters.mParentChanges);
120     mTrackedTime                   = BigEndian::HostSwap64(aMleCounters.mTrackedTime);
121     mDisabledTime                  = BigEndian::HostSwap64(aMleCounters.mDisabledTime);
122     mDetachedTime                  = BigEndian::HostSwap64(aMleCounters.mDetachedTime);
123     mChildTime                     = BigEndian::HostSwap64(aMleCounters.mChildTime);
124     mRouterTime                    = BigEndian::HostSwap64(aMleCounters.mRouterTime);
125     mLeaderTime                    = BigEndian::HostSwap64(aMleCounters.mLeaderTime);
126 }
127 
Read(MleCounters & aDiagMleCounters) const128 void MleCountersTlv::Read(MleCounters &aDiagMleCounters) const
129 {
130     aDiagMleCounters.mDisabledRole                  = BigEndian::HostSwap16(mDisabledRole);
131     aDiagMleCounters.mDetachedRole                  = BigEndian::HostSwap16(mDetachedRole);
132     aDiagMleCounters.mChildRole                     = BigEndian::HostSwap16(mChildRole);
133     aDiagMleCounters.mRouterRole                    = BigEndian::HostSwap16(mRouterRole);
134     aDiagMleCounters.mLeaderRole                    = BigEndian::HostSwap16(mLeaderRole);
135     aDiagMleCounters.mAttachAttempts                = BigEndian::HostSwap16(mAttachAttempts);
136     aDiagMleCounters.mPartitionIdChanges            = BigEndian::HostSwap16(mPartitionIdChanges);
137     aDiagMleCounters.mBetterPartitionAttachAttempts = BigEndian::HostSwap16(mBetterPartitionAttachAttempts);
138     aDiagMleCounters.mParentChanges                 = BigEndian::HostSwap16(mParentChanges);
139     aDiagMleCounters.mTrackedTime                   = BigEndian::HostSwap64(mTrackedTime);
140     aDiagMleCounters.mDisabledTime                  = BigEndian::HostSwap64(mDisabledTime);
141     aDiagMleCounters.mDetachedTime                  = BigEndian::HostSwap64(mDetachedTime);
142     aDiagMleCounters.mChildTime                     = BigEndian::HostSwap64(mChildTime);
143     aDiagMleCounters.mRouterTime                    = BigEndian::HostSwap64(mRouterTime);
144     aDiagMleCounters.mLeaderTime                    = BigEndian::HostSwap64(mLeaderTime);
145 }
146 
147 } // namespace NetworkDiagnostic
148 } // namespace ot
149