mirror of
https://github.com/espressif/openthread.git
synced 2026-09-13 20:50:05 +00:00
[netdata] add RoutePreference and related helper functions (#6916)
This commit adds helper functions to convert a `RoutePreference` to/from a 2-bit unsigned encoded value. These are used in `NetworkData` (for on-mesh prefix or external route) and also in `RoutingManager` and `RouterAdv`. This change ensures that we do not use bitwise shift of a signed and potentially negative value (`a >> b` where `a` is negative). Note that the behavior of right bitwise shift of a negative value is not specified by C++ standard and it is implementation/toolchain dependent.
This commit is contained in:
@@ -129,33 +129,15 @@ RouteInfoOption::RouteInfoOption(void)
|
||||
mPrefix.Clear();
|
||||
}
|
||||
|
||||
void RouteInfoOption::SetPreference(otRoutePreference aPreference)
|
||||
void RouteInfoOption::SetPreference(RoutePreference aPreference)
|
||||
{
|
||||
mReserved &= ~kPreferenceMask;
|
||||
mReserved |= (static_cast<uint8_t>(aPreference) << kPreferenceOffset) & kPreferenceMask;
|
||||
mReserved |= (NetworkData::RoutePreferenceToValue(aPreference) << kPreferenceOffset) & kPreferenceMask;
|
||||
}
|
||||
|
||||
otRoutePreference RouteInfoOption::GetPreference(void) const
|
||||
RouteInfoOption::RoutePreference RouteInfoOption::GetPreference(void) const
|
||||
{
|
||||
otRoutePreference preference;
|
||||
|
||||
switch ((mReserved & kPreferenceMask) >> kPreferenceOffset)
|
||||
{
|
||||
case kPreferenceLow:
|
||||
preference = OT_ROUTE_PREFERENCE_LOW;
|
||||
break;
|
||||
case kPreferenceMed:
|
||||
preference = OT_ROUTE_PREFERENCE_MED;
|
||||
break;
|
||||
case kPreferenceHigh:
|
||||
preference = OT_ROUTE_PREFERENCE_HIGH;
|
||||
break;
|
||||
default:
|
||||
preference = OT_ROUTE_PREFERENCE_LOW;
|
||||
break;
|
||||
}
|
||||
|
||||
return preference;
|
||||
return NetworkData::RoutePreferenceFromValue((mReserved & kPreferenceMask) >> kPreferenceOffset);
|
||||
}
|
||||
|
||||
void RouteInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
|
||||
@@ -180,11 +162,8 @@ Ip6::Prefix RouteInfoOption::GetPrefix(void) const
|
||||
|
||||
bool RouteInfoOption::IsValid(void) const
|
||||
{
|
||||
otRoutePreference pref = GetPreference();
|
||||
|
||||
return (GetLength() == 1 || GetLength() == 2 || GetLength() == 3) &&
|
||||
(mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT) &&
|
||||
(pref == OT_ROUTE_PREFERENCE_LOW || pref == OT_ROUTE_PREFERENCE_MED || pref == OT_ROUTE_PREFERENCE_HIGH);
|
||||
(mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT) && NetworkData::IsRoutePreferenceValid(GetPreference());
|
||||
}
|
||||
|
||||
void RouterAdvMessage::SetToDefault(void)
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "common/equatable.hpp"
|
||||
#include "net/icmp6.hpp"
|
||||
#include "net/ip6.hpp"
|
||||
#include "thread/network_data_types.hpp"
|
||||
|
||||
using ot::Encoding::BigEndian::HostSwap16;
|
||||
using ot::Encoding::BigEndian::HostSwap32;
|
||||
@@ -298,6 +299,12 @@ OT_TOOL_PACKED_BEGIN
|
||||
class RouteInfoOption : public Option
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This type represents a route preference.
|
||||
*
|
||||
*/
|
||||
typedef NetworkData::RoutePreference RoutePreference;
|
||||
|
||||
/**
|
||||
* This constructor initializes this option with zero prefix length.
|
||||
*
|
||||
@@ -310,7 +317,7 @@ public:
|
||||
* @param[in] aPreference The route preference.
|
||||
*
|
||||
*/
|
||||
void SetPreference(otRoutePreference aPreference);
|
||||
void SetPreference(RoutePreference aPreference);
|
||||
|
||||
/**
|
||||
* This method returns the route preference.
|
||||
@@ -318,7 +325,7 @@ public:
|
||||
* @returns The route preference.
|
||||
*
|
||||
*/
|
||||
otRoutePreference GetPreference(void) const;
|
||||
RoutePreference GetPreference(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the lifetime of the route in seconds.
|
||||
@@ -361,12 +368,8 @@ public:
|
||||
bool IsValid(void) const;
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kPreferenceMask = 0x18;
|
||||
static constexpr uint8_t kPreferenceOffset = 3;
|
||||
|
||||
static constexpr uint8_t kPreferenceLow = 0x03;
|
||||
static constexpr uint8_t kPreferenceMed = 0x00;
|
||||
static constexpr uint8_t kPreferenceHigh = 0x01;
|
||||
static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset;
|
||||
|
||||
uint8_t mPrefixLength; // The prefix length in bits.
|
||||
uint8_t mReserved; // The reserved field.
|
||||
|
||||
@@ -413,7 +413,7 @@ Error RoutingManager::PublishLocalOmrPrefix(void)
|
||||
omrPrefixConfig.mPreferred = true;
|
||||
omrPrefixConfig.mOnMesh = true;
|
||||
omrPrefixConfig.mDefaultRoute = false;
|
||||
omrPrefixConfig.mPreference = OT_ROUTE_PREFERENCE_MED;
|
||||
omrPrefixConfig.mPreference = NetworkData::kRoutePreferenceMedium;
|
||||
|
||||
error = Get<NetworkData::Local>().AddOnMeshPrefix(omrPrefixConfig);
|
||||
if (error != kErrorNone)
|
||||
@@ -449,7 +449,7 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
Error RoutingManager::AddExternalRoute(const Ip6::Prefix &aPrefix, otRoutePreference aRoutePreference)
|
||||
Error RoutingManager::AddExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference)
|
||||
{
|
||||
Error error;
|
||||
NetworkData::ExternalRouteConfig routeConfig;
|
||||
@@ -519,7 +519,7 @@ const Ip6::Prefix *RoutingManager::EvaluateOnLinkPrefix(void)
|
||||
if (smallestOnLinkPrefix == nullptr)
|
||||
{
|
||||
if (mIsAdvertisingLocalOnLinkPrefix ||
|
||||
(AddExternalRoute(mLocalOnLinkPrefix, OT_ROUTE_PREFERENCE_MED) == kErrorNone))
|
||||
(AddExternalRoute(mLocalOnLinkPrefix, NetworkData::kRoutePreferenceMedium) == kErrorNone))
|
||||
{
|
||||
newOnLinkPrefix = &mLocalOnLinkPrefix;
|
||||
}
|
||||
@@ -1092,7 +1092,7 @@ bool RoutingManager::UpdateDiscoveredPrefixes(const RouterAdv::PrefixInfoOption
|
||||
|
||||
if (!mDiscoveredPrefixes.IsFull())
|
||||
{
|
||||
SuccessOrExit(AddExternalRoute(prefix, OT_ROUTE_PREFERENCE_MED));
|
||||
SuccessOrExit(AddExternalRoute(prefix, NetworkData::kRoutePreferenceMedium));
|
||||
existingPrefix = mDiscoveredPrefixes.PushBack();
|
||||
*existingPrefix = onLinkPrefix;
|
||||
needReevaluate = true;
|
||||
|
||||
@@ -170,6 +170,8 @@ public:
|
||||
Error HandleInfraIfStateChanged(uint32_t aInfraIfIndex, bool aIsRunning);
|
||||
|
||||
private:
|
||||
typedef NetworkData::RoutePreference RoutePreference;
|
||||
|
||||
static constexpr uint16_t kMaxRouterAdvMessageLength = 256; // The maximum RA message length we can handle.
|
||||
|
||||
// The maximum number of the OMR prefixes to advertise.
|
||||
@@ -233,7 +235,7 @@ private:
|
||||
|
||||
// The preference of this route, available
|
||||
// only when `mIsOnLinkPrefix` is FALSE.
|
||||
otRoutePreference mRoutePreference;
|
||||
RoutePreference mRoutePreference;
|
||||
};
|
||||
TimeMilli mTimeLastUpdate;
|
||||
bool mIsOnLinkPrefix;
|
||||
@@ -280,7 +282,7 @@ private:
|
||||
void EvaluateOmrPrefix(OmrPrefixArray &aNewOmrPrefixes);
|
||||
Error PublishLocalOmrPrefix(void);
|
||||
void UnpublishLocalOmrPrefix(void);
|
||||
Error AddExternalRoute(const Ip6::Prefix &aPrefix, otRoutePreference aRoutePreference);
|
||||
Error AddExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference);
|
||||
void RemoveExternalRoute(const Ip6::Prefix &aPrefix);
|
||||
void StartRouterSolicitationDelay(void);
|
||||
Error SendRouterSolicitation(void);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "common/locator_getters.hpp"
|
||||
#include "common/logging.hpp"
|
||||
#include "net/udp6.hpp"
|
||||
#include "thread/network_data_types.hpp"
|
||||
#include "thread/thread_netif.hpp"
|
||||
|
||||
/**
|
||||
@@ -352,7 +353,7 @@ Error Client::AddressResponse::GetNat64Prefix(Ip6::Prefix &aPrefix) const
|
||||
{
|
||||
Error error = kErrorNotFound;
|
||||
NetworkData::Iterator iterator = NetworkData::kIteratorInit;
|
||||
signed int preference = OT_ROUTE_PREFERENCE_LOW;
|
||||
signed int preference = NetworkData::kRoutePreferenceLow;
|
||||
NetworkData::ExternalRouteConfig config;
|
||||
|
||||
aPrefix.Clear();
|
||||
|
||||
@@ -453,10 +453,7 @@ public:
|
||||
* @returns The preference field from the @p aFlags.
|
||||
*
|
||||
*/
|
||||
static int8_t PreferenceFromFlags(uint8_t aFlags)
|
||||
{
|
||||
return static_cast<int8_t>(static_cast<int8_t>(aFlags) >> kPreferenceOffset);
|
||||
}
|
||||
static int8_t PreferenceFromFlags(uint8_t aFlags) { return RoutePreferenceFromValue(aFlags >> kPreferenceOffset); }
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kPreferenceOffset = 6;
|
||||
@@ -1025,7 +1022,7 @@ public:
|
||||
*/
|
||||
static int8_t PreferenceFromFlags(uint16_t aFlags)
|
||||
{
|
||||
return static_cast<int8_t>(static_cast<int16_t>(aFlags) >> kPreferenceOffset);
|
||||
return RoutePreferenceFromValue(static_cast<uint8_t>(aFlags >> kPreferenceOffset));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -41,11 +41,6 @@ namespace NetworkData {
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
|
||||
static bool IsPreferenceValid(int8_t aPrf)
|
||||
{
|
||||
return (aPrf == OT_ROUTE_PREFERENCE_LOW) || (aPrf == OT_ROUTE_PREFERENCE_MED) || (aPrf == OT_ROUTE_PREFERENCE_HIGH);
|
||||
}
|
||||
|
||||
static bool IsPrefixValid(Instance &aInstance, const Ip6::Prefix &aPrefix)
|
||||
{
|
||||
// Check that prefix length is within the valid range and the prefix
|
||||
@@ -73,7 +68,7 @@ bool OnMeshPrefixConfig::IsValid(Instance &aInstance) const
|
||||
VerifyOrExit(GetPrefix().GetLength() == Ip6::NetworkPrefix::kLength);
|
||||
}
|
||||
|
||||
VerifyOrExit(IsPreferenceValid(mPreference));
|
||||
VerifyOrExit(IsRoutePreferenceValid(mPreference));
|
||||
VerifyOrExit(IsPrefixValid(aInstance, GetPrefix()));
|
||||
VerifyOrExit(GetPrefix().GetLength() > 0);
|
||||
|
||||
@@ -129,7 +124,7 @@ uint16_t OnMeshPrefixConfig::ConvertToTlvFlags(void) const
|
||||
}
|
||||
#endif
|
||||
|
||||
flags |= (static_cast<uint16_t>(mPreference) << BorderRouterEntry::kPreferenceOffset);
|
||||
flags |= (static_cast<uint16_t>(RoutePreferenceToValue(mPreference)) << BorderRouterEntry::kPreferenceOffset);
|
||||
|
||||
return flags;
|
||||
}
|
||||
@@ -158,7 +153,7 @@ void OnMeshPrefixConfig::SetFromTlvFlags(uint16_t aFlags)
|
||||
mOnMesh = ((aFlags & BorderRouterEntry::kOnMeshFlag) != 0);
|
||||
mNdDns = ((aFlags & BorderRouterEntry::kNdDnsFlag) != 0);
|
||||
mDp = ((aFlags & BorderRouterEntry::kDpFlag) != 0);
|
||||
mPreference = static_cast<int8_t>(aFlags >> BorderRouterEntry::kPreferenceOffset);
|
||||
mPreference = RoutePreferenceFromValue(static_cast<uint8_t>(aFlags >> BorderRouterEntry::kPreferenceOffset));
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
@@ -171,7 +166,7 @@ bool ExternalRouteConfig::IsValid(Instance &aInstance) const
|
||||
VerifyOrExit(GetPrefix().IsValidNat64());
|
||||
}
|
||||
|
||||
VerifyOrExit(IsPreferenceValid(mPreference));
|
||||
VerifyOrExit(IsRoutePreferenceValid(mPreference));
|
||||
VerifyOrExit(IsPrefixValid(aInstance, GetPrefix()));
|
||||
|
||||
isValid = true;
|
||||
@@ -189,7 +184,7 @@ uint8_t ExternalRouteConfig::ConvertToTlvFlags(void) const
|
||||
flags |= HasRouteEntry::kNat64Flag;
|
||||
}
|
||||
|
||||
flags |= (static_cast<uint8_t>(mPreference) << HasRouteEntry::kPreferenceOffset);
|
||||
flags |= (RoutePreferenceToValue(mPreference) << HasRouteEntry::kPreferenceOffset);
|
||||
|
||||
return flags;
|
||||
}
|
||||
@@ -213,7 +208,7 @@ void ExternalRouteConfig::SetFrom(Instance & aInstance,
|
||||
void ExternalRouteConfig::SetFromTlvFlags(uint8_t aFlags)
|
||||
{
|
||||
mNat64 = ((aFlags & HasRouteEntry::kNat64Flag) != 0);
|
||||
mPreference = static_cast<int8_t>(aFlags >> HasRouteEntry::kPreferenceOffset);
|
||||
mPreference = RoutePreferenceFromValue(aFlags >> HasRouteEntry::kPreferenceOffset);
|
||||
}
|
||||
|
||||
bool ServiceConfig::ServerConfig::operator==(const ServerConfig &aOther) const
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <openthread/netdata.h>
|
||||
|
||||
#include "common/clearable.hpp"
|
||||
#include "common/debug.hpp"
|
||||
#include "common/equatable.hpp"
|
||||
#include "net/ip6_address.hpp"
|
||||
|
||||
@@ -65,6 +66,76 @@ class HasRouteEntry;
|
||||
class ServiceTlv;
|
||||
class ServerTlv;
|
||||
|
||||
/**
|
||||
* This enumeration type represents the route preference values as a signed integer (per RFC-4191).
|
||||
*
|
||||
*/
|
||||
enum RoutePreference : int8_t
|
||||
{
|
||||
kRoutePreferenceLow = OT_ROUTE_PREFERENCE_LOW, ///< Low route preference.
|
||||
kRoutePreferenceMedium = OT_ROUTE_PREFERENCE_MED, ///< Medium route preference.
|
||||
kRoutePreferenceHigh = OT_ROUTE_PREFERENCE_HIGH, ///< High route preference.
|
||||
};
|
||||
|
||||
/**
|
||||
* This function indicates whether a given `int8_t` preference value is a valid route preference (i.e., one of the
|
||||
* values from `RoutePreference` enumeration).
|
||||
*
|
||||
* @param[in] aPref The signed route preference value.
|
||||
*
|
||||
* @retval TRUE if @p aPref is valid.
|
||||
* @retval FALSE if @p aPref is not valid
|
||||
*
|
||||
*/
|
||||
inline bool IsRoutePreferenceValid(int8_t aPref)
|
||||
{
|
||||
return (aPref == kRoutePreferenceLow) || (aPref == kRoutePreferenceMedium) || (aPref == kRoutePreferenceHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function coverts a route preference to a 2-bit unsigned value.
|
||||
*
|
||||
* The @p aPref MUST be valid (value from `RoutePreference` enumeration), or the behavior is undefined.
|
||||
*
|
||||
* @param[in] aPref The route preference to convert.
|
||||
*
|
||||
* @returns The 2-bit unsigned value representing @p aPref.
|
||||
*
|
||||
*/
|
||||
inline uint8_t RoutePreferenceToValue(int8_t aPref)
|
||||
{
|
||||
constexpr uint8_t kHigh = 1; // 01
|
||||
constexpr uint8_t kMedium = 0; // 00
|
||||
constexpr uint8_t kLow = 3; // 11
|
||||
|
||||
OT_ASSERT(IsRoutePreferenceValid(aPref));
|
||||
|
||||
return (aPref == 0) ? kMedium : ((aPref > 0) ? kHigh : kLow);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function coverts a 2-bit unsigned value to a route preference.
|
||||
*
|
||||
* @param[in] aValue The 2-bit unsigned value to convert from. Note that only the first two bits of @p aValue
|
||||
* are used and the rest of bits are ignored.
|
||||
*
|
||||
* @returns The route preference corresponding to @p aValue.
|
||||
*
|
||||
*/
|
||||
inline RoutePreference RoutePreferenceFromValue(uint8_t aValue)
|
||||
{
|
||||
constexpr uint8_t kMask = 3; // First two bits.
|
||||
|
||||
static const RoutePreference kRoutePreferences[] = {
|
||||
/* 0 (00) -> */ kRoutePreferenceMedium,
|
||||
/* 1 (01) -> */ kRoutePreferenceHigh,
|
||||
/* 2 (10) -> */ kRoutePreferenceMedium, // Per RFC-4191, the reserved value (10) MUST be treated as (00)
|
||||
/* 3 (11) -> */ kRoutePreferenceLow,
|
||||
};
|
||||
|
||||
return kRoutePreferences[aValue & kMask];
|
||||
}
|
||||
|
||||
/**
|
||||
* This class represents an On-mesh Prefix (Border Router) configuration.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user