1 /*
2  *  Copyright (c) 2019, 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 of MLE types and constants.
32  */
33 
34 #include "mle_types.hpp"
35 
36 #include "common/array.hpp"
37 #include "common/code_utils.hpp"
38 #include "common/message.hpp"
39 #include "common/random.hpp"
40 #include "utils/static_counter.hpp"
41 
42 namespace ot {
43 namespace Mle {
44 
45 //---------------------------------------------------------------------------------------------------------------------
46 // DeviceMode
47 
Get(ModeConfig & aModeConfig) const48 void DeviceMode::Get(ModeConfig &aModeConfig) const
49 {
50     aModeConfig.mRxOnWhenIdle = IsRxOnWhenIdle();
51     aModeConfig.mDeviceType   = IsFullThreadDevice();
52     aModeConfig.mNetworkData  = (GetNetworkDataType() == NetworkData::kFullSet);
53 }
54 
Set(const ModeConfig & aModeConfig)55 void DeviceMode::Set(const ModeConfig &aModeConfig)
56 {
57     mMode = kModeReserved;
58     mMode |= aModeConfig.mRxOnWhenIdle ? kModeRxOnWhenIdle : 0;
59     mMode |= aModeConfig.mDeviceType ? kModeFullThreadDevice : 0;
60     mMode |= aModeConfig.mNetworkData ? kModeFullNetworkData : 0;
61 }
62 
ToString(void) const63 DeviceMode::InfoString DeviceMode::ToString(void) const
64 {
65     InfoString string;
66 
67     string.Append("rx-on:%s ftd:%s full-net:%s", ToYesNo(IsRxOnWhenIdle()), ToYesNo(IsFullThreadDevice()),
68                   ToYesNo(GetNetworkDataType() == NetworkData::kFullSet));
69 
70     return string;
71 }
72 
73 //---------------------------------------------------------------------------------------------------------------------
74 // DeviceProperties
75 
76 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
77 
DeviceProperties(void)78 DeviceProperties::DeviceProperties(void)
79 {
80     Clear();
81 
82     mPowerSupply            = OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY;
83     mLeaderWeightAdjustment = kDefaultAdjustment;
84 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
85     mIsBorderRouter = true;
86 #endif
87 }
88 
ClampWeightAdjustment(void)89 void DeviceProperties::ClampWeightAdjustment(void)
90 {
91     mLeaderWeightAdjustment = Clamp(mLeaderWeightAdjustment, kMinAdjustment, kMaxAdjustment);
92 }
93 
CalculateLeaderWeight(void) const94 uint8_t DeviceProperties::CalculateLeaderWeight(void) const
95 {
96     static const int8_t kPowerSupplyIncs[] = {
97         kPowerBatteryInc,          // (0) kPowerSupplyBattery
98         kPowerExternalInc,         // (1) kPowerSupplyExternal
99         kPowerExternalStableInc,   // (2) kPowerSupplyExternalStable
100         kPowerExternalUnstableInc, // (3) kPowerSupplyExternalUnstable
101     };
102 
103     struct EnumCheck
104     {
105         InitEnumValidatorCounter();
106         ValidateNextEnum(kPowerSupplyBattery);
107         ValidateNextEnum(kPowerSupplyExternal);
108         ValidateNextEnum(kPowerSupplyExternalStable);
109         ValidateNextEnum(kPowerSupplyExternalUnstable);
110     };
111 
112     uint8_t     weight      = kBaseWeight;
113     PowerSupply powerSupply = MapEnum(mPowerSupply);
114 
115     if (mIsBorderRouter)
116     {
117         weight += (mSupportsCcm ? kCcmBorderRouterInc : kBorderRouterInc);
118     }
119 
120     if (powerSupply < GetArrayLength(kPowerSupplyIncs))
121     {
122         weight += kPowerSupplyIncs[powerSupply];
123     }
124 
125     if (mIsUnstable)
126     {
127         switch (powerSupply)
128         {
129         case kPowerSupplyBattery:
130         case kPowerSupplyExternalUnstable:
131             break;
132 
133         default:
134             weight += kIsUnstableInc;
135         }
136     }
137 
138     weight += mLeaderWeightAdjustment;
139 
140     return weight;
141 }
142 
143 #endif // #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
144 
145 //---------------------------------------------------------------------------------------------------------------------
146 // RouterIdSet
147 
GetNumberOfAllocatedIds(void) const148 uint8_t RouterIdSet::GetNumberOfAllocatedIds(void) const
149 {
150     uint8_t count = 0;
151 
152     for (uint8_t byte : mRouterIdSet)
153     {
154         count += CountBitsInMask(byte);
155     }
156 
157     return count;
158 }
159 
160 //---------------------------------------------------------------------------------------------------------------------
161 // TxChallenge
162 
GenerateRandom(void)163 void TxChallenge::GenerateRandom(void) { IgnoreError(Random::Crypto::Fill(*this)); }
164 
165 //---------------------------------------------------------------------------------------------------------------------
166 // RxChallenge
167 
ReadFrom(const Message & aMessage,const OffsetRange & aOffsetRange)168 Error RxChallenge::ReadFrom(const Message &aMessage, const OffsetRange &aOffsetRange)
169 {
170     Error       error       = kErrorNone;
171     OffsetRange offsetRange = aOffsetRange;
172 
173     Clear();
174 
175     offsetRange.ShrinkLength(kMaxSize);
176 
177     VerifyOrExit(offsetRange.Contains(kMinSize), error = kErrorParse);
178 
179     SuccessOrExit(error = aMessage.Read(offsetRange, mArray.GetArrayBuffer(), offsetRange.GetLength()));
180     mArray.SetLength(static_cast<uint8_t>(offsetRange.GetLength()));
181 
182 exit:
183     return error;
184 }
185 
operator ==(const TxChallenge & aTxChallenge) const186 bool RxChallenge::operator==(const TxChallenge &aTxChallenge) const
187 {
188     return (mArray.GetLength() == kMaxSize) && (memcmp(mArray.GetArrayBuffer(), aTxChallenge.m8, kMaxSize) == 0);
189 }
190 
191 //---------------------------------------------------------------------------------------------------------------------
192 
RoleToString(DeviceRole aRole)193 const char *RoleToString(DeviceRole aRole)
194 {
195     static const char *const kRoleStrings[] = {
196         "disabled", // (0) kRoleDisabled
197         "detached", // (1) kRoleDetached
198         "child",    // (2) kRoleChild
199         "router",   // (3) kRoleRouter
200         "leader",   // (4) kRoleLeader
201     };
202 
203     struct EnumCheck
204     {
205         InitEnumValidatorCounter();
206         ValidateNextEnum(kRoleDisabled);
207         ValidateNextEnum(kRoleDetached);
208         ValidateNextEnum(kRoleChild);
209         ValidateNextEnum(kRoleRouter);
210         ValidateNextEnum(kRoleLeader);
211     };
212 
213     return (aRole < GetArrayLength(kRoleStrings)) ? kRoleStrings[aRole] : "invalid";
214 }
215 
216 } // namespace Mle
217 } // namespace ot
218