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