blob: 0c87ce6e96813480c32af80fb0a9c81315852af5 [file] [log] [blame]
/*
* Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file implements of MLE types and constants.
*/
#include "mle_types.hpp"
#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/message.hpp"
#include "common/random.hpp"
namespace ot {
namespace Mle {
//---------------------------------------------------------------------------------------------------------------------
// DeviceMode
void DeviceMode::Get(ModeConfig &aModeConfig) const
{
aModeConfig.mRxOnWhenIdle = IsRxOnWhenIdle();
aModeConfig.mDeviceType = IsFullThreadDevice();
aModeConfig.mNetworkData = (GetNetworkDataType() == NetworkData::kFullSet);
}
void DeviceMode::Set(const ModeConfig &aModeConfig)
{
mMode = kModeReserved;
mMode |= aModeConfig.mRxOnWhenIdle ? kModeRxOnWhenIdle : 0;
mMode |= aModeConfig.mDeviceType ? kModeFullThreadDevice : 0;
mMode |= aModeConfig.mNetworkData ? kModeFullNetworkData : 0;
}
DeviceMode::InfoString DeviceMode::ToString(void) const
{
InfoString string;
string.Append("rx-on:%s ftd:%s full-net:%s", ToYesNo(IsRxOnWhenIdle()), ToYesNo(IsFullThreadDevice()),
ToYesNo(GetNetworkDataType() == NetworkData::kFullSet));
return string;
}
//---------------------------------------------------------------------------------------------------------------------
// DeviceProperties
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
DeviceProperties::DeviceProperties(void)
{
Clear();
mPowerSupply = OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY;
mLeaderWeightAdjustment = kDefaultAdjustment;
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
mIsBorderRouter = true;
#endif
}
void DeviceProperties::ClampWeightAdjustment(void)
{
mLeaderWeightAdjustment = Clamp(mLeaderWeightAdjustment, kMinAdjustment, kMaxAdjustment);
}
uint8_t DeviceProperties::CalculateLeaderWeight(void) const
{
static const int8_t kPowerSupplyIncs[] = {
kPowerBatteryInc, // (0) kPowerSupplyBattery
kPowerExternalInc, // (1) kPowerSupplyExternal
kPowerExternalStableInc, // (2) kPowerSupplyExternalStable
kPowerExternalUnstableInc, // (3) kPowerSupplyExternalUnstable
};
static_assert(0 == kPowerSupplyBattery, "kPowerSupplyBattery value is incorrect");
static_assert(1 == kPowerSupplyExternal, "kPowerSupplyExternal value is incorrect");
static_assert(2 == kPowerSupplyExternalStable, "kPowerSupplyExternalStable value is incorrect");
static_assert(3 == kPowerSupplyExternalUnstable, "kPowerSupplyExternalUnstable value is incorrect");
uint8_t weight = kBaseWeight;
PowerSupply powerSupply = MapEnum(mPowerSupply);
if (mIsBorderRouter)
{
weight += (mSupportsCcm ? kCcmBorderRouterInc : kBorderRouterInc);
}
if (powerSupply < GetArrayLength(kPowerSupplyIncs))
{
weight += kPowerSupplyIncs[powerSupply];
}
if (mIsUnstable)
{
switch (powerSupply)
{
case kPowerSupplyBattery:
case kPowerSupplyExternalUnstable:
break;
default:
weight += kIsUnstableInc;
}
}
weight += mLeaderWeightAdjustment;
return weight;
}
#endif // #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
//---------------------------------------------------------------------------------------------------------------------
// RouterIdSet
uint8_t RouterIdSet::GetNumberOfAllocatedIds(void) const
{
uint8_t count = 0;
for (uint8_t byte : mRouterIdSet)
{
count += CountBitsInMask(byte);
}
return count;
}
//---------------------------------------------------------------------------------------------------------------------
// TxChallenge
void TxChallenge::GenerateRandom(void) { IgnoreError(Random::Crypto::Fill(*this)); }
//---------------------------------------------------------------------------------------------------------------------
// RxChallenge
Error RxChallenge::ReadFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
{
Error error = kErrorNone;
Clear();
aLength = Min<uint16_t>(aLength, kMaxSize);
VerifyOrExit(kMinSize <= aLength, error = kErrorParse);
SuccessOrExit(error = aMessage.Read(aOffset, mArray.GetArrayBuffer(), aLength));
mArray.SetLength(static_cast<uint8_t>(aLength));
exit:
return error;
}
bool RxChallenge::operator==(const TxChallenge &aTxChallenge) const
{
return (mArray.GetLength() == kMaxSize) && (memcmp(mArray.GetArrayBuffer(), aTxChallenge.m8, kMaxSize) == 0);
}
//---------------------------------------------------------------------------------------------------------------------
const char *RoleToString(DeviceRole aRole)
{
static const char *const kRoleStrings[] = {
"disabled", // (0) kRoleDisabled
"detached", // (1) kRoleDetached
"child", // (2) kRoleChild
"router", // (3) kRoleRouter
"leader", // (4) kRoleLeader
};
static_assert(kRoleDisabled == 0, "kRoleDisabled value is incorrect");
static_assert(kRoleDetached == 1, "kRoleDetached value is incorrect");
static_assert(kRoleChild == 2, "kRoleChild value is incorrect");
static_assert(kRoleRouter == 3, "kRoleRouter value is incorrect");
static_assert(kRoleLeader == 4, "kRoleLeader value is incorrect");
return (aRole < GetArrayLength(kRoleStrings)) ? kRoleStrings[aRole] : "invalid";
}
} // namespace Mle
} // namespace ot