[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:
Abtin Keshavarzian
2021-08-12 14:13:16 -07:00
committed by GitHub
parent cd6d57d1af
commit 02ff2110da
8 changed files with 104 additions and 56 deletions
@@ -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.
+4 -4
View File
@@ -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;
+4 -2
View File
@@ -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);
+2 -1
View File
@@ -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();
+2 -5
View File
@@ -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:
+6 -11
View File
@@ -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
+71
View File
@@ -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.
*