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