mirror of
https://github.com/espressif/openthread.git
synced 2026-08-22 10:29:52 +00:00
[routing-manager] prepare route/prefix info options in place (#7699)
This commit contains smaller enhancements in `RoutingManager ` and `Prefix/RouteInfoOption`. This commit changes how the options are added in a message so that we directly construct the option in the message buffer (instead of creating it separately and then copying the bytes). It also changes `RouteInfoOption::IsValid()` to validate that the option length can fit the specified prefix length.
This commit is contained in:
@@ -40,9 +40,7 @@
|
||||
#include "common/code_utils.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
namespace BorderRouter {
|
||||
|
||||
namespace RouterAdv {
|
||||
|
||||
const Option *Option::GetNextOption(const Option *aCurOption, const uint8_t *aBuffer, uint16_t aBufferLength)
|
||||
@@ -70,41 +68,16 @@ exit:
|
||||
return reinterpret_cast<const Option *>(nextOption);
|
||||
}
|
||||
|
||||
PrefixInfoOption::PrefixInfoOption(void)
|
||||
: Option(Type::kPrefixInfo, sizeof(*this) / kLengthUnit)
|
||||
, mPrefixLength(0)
|
||||
, mReserved1(0)
|
||||
, mValidLifetime(0)
|
||||
, mPreferredLifetime(0)
|
||||
, mReserved2(0)
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// PrefixInfoOption
|
||||
|
||||
void PrefixInfoOption::Init(void)
|
||||
{
|
||||
Clear();
|
||||
SetType(Type::kPrefixInfo);
|
||||
SetSize(sizeof(PrefixInfoOption));
|
||||
|
||||
OT_UNUSED_VARIABLE(mReserved2);
|
||||
|
||||
mPrefix.Clear();
|
||||
}
|
||||
|
||||
void PrefixInfoOption::SetOnLink(bool aOnLink)
|
||||
{
|
||||
if (aOnLink)
|
||||
{
|
||||
mReserved1 |= kOnLinkFlagMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
mReserved1 &= ~kOnLinkFlagMask;
|
||||
}
|
||||
}
|
||||
|
||||
void PrefixInfoOption::SetAutoAddrConfig(bool aAutoAddrConfig)
|
||||
{
|
||||
if (aAutoAddrConfig)
|
||||
{
|
||||
mReserved1 |= kAutoConfigFlagMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
mReserved1 &= ~kAutoConfigFlagMask;
|
||||
}
|
||||
}
|
||||
|
||||
void PrefixInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
|
||||
@@ -113,62 +86,89 @@ void PrefixInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
|
||||
mPrefix = AsCoreType(&aPrefix.mPrefix);
|
||||
}
|
||||
|
||||
Ip6::Prefix PrefixInfoOption::GetPrefix(void) const
|
||||
void PrefixInfoOption::GetPrefix(Ip6::Prefix &aPrefix) const
|
||||
{
|
||||
Ip6::Prefix prefix;
|
||||
|
||||
prefix.Set(mPrefix.GetBytes(), mPrefixLength);
|
||||
return prefix;
|
||||
aPrefix.Set(mPrefix.GetBytes(), mPrefixLength);
|
||||
}
|
||||
|
||||
RouteInfoOption::RouteInfoOption(void)
|
||||
: Option(Type::kRouteInfo, 0)
|
||||
, mPrefixLength(0)
|
||||
, mReserved(0)
|
||||
, mRouteLifetime(0)
|
||||
bool PrefixInfoOption::IsValid(void) const
|
||||
{
|
||||
OT_UNUSED_VARIABLE(mReserved);
|
||||
return (GetSize() >= sizeof(*this)) && (mPrefixLength <= Ip6::Prefix::kMaxLength) &&
|
||||
(GetPreferredLifetime() <= GetValidLifetime());
|
||||
}
|
||||
|
||||
mPrefix.Clear();
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// RouteInfoOption
|
||||
|
||||
void RouteInfoOption::Init(void)
|
||||
{
|
||||
Clear();
|
||||
SetType(Type::kRouteInfo);
|
||||
}
|
||||
|
||||
void RouteInfoOption::SetPreference(RoutePreference aPreference)
|
||||
{
|
||||
mReserved &= ~kPreferenceMask;
|
||||
mReserved |= (NetworkData::RoutePreferenceToValue(aPreference) << kPreferenceOffset) & kPreferenceMask;
|
||||
mResvdPrf &= ~kPreferenceMask;
|
||||
mResvdPrf |= (NetworkData::RoutePreferenceToValue(aPreference) << kPreferenceOffset) & kPreferenceMask;
|
||||
}
|
||||
|
||||
RouteInfoOption::RoutePreference RouteInfoOption::GetPreference(void) const
|
||||
{
|
||||
return NetworkData::RoutePreferenceFromValue((mReserved & kPreferenceMask) >> kPreferenceOffset);
|
||||
return NetworkData::RoutePreferenceFromValue((mResvdPrf & kPreferenceMask) >> kPreferenceOffset);
|
||||
}
|
||||
|
||||
void RouteInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
|
||||
{
|
||||
// The total length (in bytes) of a Router Information Option
|
||||
// is: (8 bytes fixed option header) + (0, 8, or 16 bytes prefix).
|
||||
// Because the length of the option must be padded with 8 bytes,
|
||||
// the length of the prefix (in bits) must be padded with 64 bits.
|
||||
SetLength((aPrefix.mLength + kLengthUnit * CHAR_BIT - 1) / (kLengthUnit * CHAR_BIT) + 1);
|
||||
|
||||
SetLength(OptionLengthForPrefix(aPrefix.mLength));
|
||||
mPrefixLength = aPrefix.mLength;
|
||||
mPrefix = AsCoreType(&aPrefix.mPrefix);
|
||||
memcpy(GetPrefixBytes(), aPrefix.GetBytes(), aPrefix.GetBytesSize());
|
||||
}
|
||||
|
||||
Ip6::Prefix RouteInfoOption::GetPrefix(void) const
|
||||
void RouteInfoOption::GetPrefix(Ip6::Prefix &aPrefix) const
|
||||
{
|
||||
Ip6::Prefix prefix;
|
||||
|
||||
prefix.Set(mPrefix.GetBytes(), mPrefixLength);
|
||||
return prefix;
|
||||
aPrefix.Set(GetPrefixBytes(), mPrefixLength);
|
||||
}
|
||||
|
||||
bool RouteInfoOption::IsValid(void) const
|
||||
{
|
||||
return (GetLength() == 1 || GetLength() == 2 || GetLength() == 3) &&
|
||||
(mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT) && NetworkData::IsRoutePreferenceValid(GetPreference());
|
||||
return (GetSize() >= kMinSize) && (mPrefixLength <= Ip6::Prefix::kMaxLength) &&
|
||||
(GetLength() >= OptionLengthForPrefix(mPrefixLength)) &&
|
||||
NetworkData::IsRoutePreferenceValid(GetPreference());
|
||||
}
|
||||
|
||||
uint8_t RouteInfoOption::OptionLengthForPrefix(uint8_t aPrefixLength)
|
||||
{
|
||||
static constexpr uint8_t kMaxPrefixLenForOptionLen1 = 0;
|
||||
static constexpr uint8_t kMaxPrefixLenForOptionLen2 = 64;
|
||||
|
||||
uint8_t length;
|
||||
|
||||
// The Option Length can be 1, 2, or 3 depending on the prefix
|
||||
// length
|
||||
//
|
||||
// - 1 when prefix len is zero.
|
||||
// - 2 when prefix len is less then or equal to 64.
|
||||
// - 3 otherwise.
|
||||
|
||||
if (aPrefixLength == kMaxPrefixLenForOptionLen1)
|
||||
{
|
||||
length = 1;
|
||||
}
|
||||
else if (aPrefixLength <= kMaxPrefixLenForOptionLen2)
|
||||
{
|
||||
length = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
length = 3;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// RouterAdvMessage
|
||||
|
||||
void RouterAdvMessage::SetToDefault(void)
|
||||
{
|
||||
mHeader.Clear();
|
||||
@@ -196,6 +196,9 @@ bool RouterAdvMessage::operator==(const RouterAdvMessage &aOther) const
|
||||
mReachableTime == aOther.mReachableTime && mRetransTimer == aOther.mRetransTimer;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// RouterAdvMessage
|
||||
|
||||
RouterSolicitMessage::RouterSolicitMessage(void)
|
||||
{
|
||||
mHeader.Clear();
|
||||
@@ -203,9 +206,7 @@ RouterSolicitMessage::RouterSolicitMessage(void)
|
||||
}
|
||||
|
||||
} // namespace RouterAdv
|
||||
|
||||
} // namespace BorderRouter
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <openthread/netdata.h>
|
||||
#include <openthread/platform/toolchain.h>
|
||||
|
||||
#include "common/const_cast.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/equatable.hpp"
|
||||
#include "net/icmp6.hpp"
|
||||
@@ -56,14 +57,11 @@ using ot::Encoding::BigEndian::HostSwap16;
|
||||
using ot::Encoding::BigEndian::HostSwap32;
|
||||
|
||||
namespace ot {
|
||||
|
||||
namespace BorderRouter {
|
||||
|
||||
namespace RouterAdv {
|
||||
|
||||
/**
|
||||
* This class represents the variable length options in Neighbor
|
||||
* Discovery messages.
|
||||
* This class represents the variable length options in Neighbor Discovery messages.
|
||||
*
|
||||
* @sa PrefixInfoOption
|
||||
* @sa RouteInfoOption
|
||||
@@ -79,23 +77,10 @@ public:
|
||||
kRouteInfo = 24, ///< Route Information Option.
|
||||
};
|
||||
|
||||
static constexpr uint8_t kLengthUnit = 8; ///< The unit of length in octets.
|
||||
static constexpr uint16_t kLengthUnit = 8; ///< The unit of length in octets.
|
||||
|
||||
/**
|
||||
* This constructor initializes the option with given type and length.
|
||||
*
|
||||
* @param[in] aType The type of this option.
|
||||
* @param[in] aLength The length of this option in unit of 8 octets.
|
||||
*
|
||||
*/
|
||||
explicit Option(Type aType, uint8_t aLength = 0)
|
||||
: mType(aType)
|
||||
, mLength(aLength)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the type of this option.
|
||||
* This method gets the option type.
|
||||
*
|
||||
* @returns The option type.
|
||||
*
|
||||
@@ -103,20 +88,28 @@ public:
|
||||
Type GetType(void) const { return mType; }
|
||||
|
||||
/**
|
||||
* This method sets the size of the option (in bytes).
|
||||
* This method sets the option type.
|
||||
*
|
||||
* Since the option must end on their natural 64-bits boundaries,
|
||||
* the actual length set to the option is padded to (aSize + 7) / 8 * 8.
|
||||
* @param[in] aType The option type.
|
||||
*
|
||||
* @param[in] aSize The size of the option in unit of 1 byte.
|
||||
*
|
||||
*/
|
||||
void SetType(Type aType) { mType = aType; }
|
||||
|
||||
/**
|
||||
* This method sets the length based on a given total option size in bytes.
|
||||
*
|
||||
* Th option must end on a 64-bit boundary, so the length is derived as `(aSize + 7) / 8 * 8`.
|
||||
*
|
||||
* @param[in] aSize The size of option in bytes.
|
||||
*
|
||||
*/
|
||||
void SetSize(uint16_t aSize) { mLength = static_cast<uint8_t>((aSize + kLengthUnit - 1) / kLengthUnit); }
|
||||
|
||||
/**
|
||||
* This method returns the size of the option (in bytes).
|
||||
* This method returns the size of the option in bytes.
|
||||
*
|
||||
* @returns The size of the option in unit of 1 byte.
|
||||
* @returns The size of the option in bytes.
|
||||
*
|
||||
*/
|
||||
uint16_t GetSize(void) const { return mLength * kLengthUnit; }
|
||||
@@ -150,72 +143,81 @@ public:
|
||||
static const Option *GetNextOption(const Option *aCurOption, const uint8_t *aBuffer, uint16_t aBufferLength);
|
||||
|
||||
/**
|
||||
* This method tells whether this option is valid.
|
||||
* This method indicates whether or not this option is valid.
|
||||
*
|
||||
* @return A boolean that indicates whether this option is valid.
|
||||
* @retval TRUE The option is valid.
|
||||
* @retval FALSE The option is not valid.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return mLength > 0; }
|
||||
|
||||
private:
|
||||
Type mType; // Type of the option.
|
||||
uint8_t mLength; // Length of the option in unit of 8 octets,
|
||||
// including the `type` and `length` fields.
|
||||
uint8_t mLength; // Length of the option in unit of 8 octets, including the `mType` and `mLength` fields.
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class represents the Prefix Information Option.
|
||||
*
|
||||
* See section 4.6.2 of RFC 4861 for definition of this option.
|
||||
* https://tools.ietf.org/html/rfc4861#section-4.6.2
|
||||
* See section 4.6.2 of RFC 4861 for definition of this option [https://tools.ietf.org/html/rfc4861#section-4.6.2]
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class PrefixInfoOption : public Option
|
||||
class PrefixInfoOption : public Option, private Clearable<PrefixInfoOption>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes this option with zero prefix
|
||||
* length, valid lifetime and preferred lifetime.
|
||||
*
|
||||
*/
|
||||
PrefixInfoOption(void);
|
||||
static constexpr Type kType = Type::kPrefixInfo; ///< Prefix Information Option Type.
|
||||
|
||||
/**
|
||||
* This method returns the on-link flag.
|
||||
*
|
||||
* @returns A boolean which indicates whether the on-link flag is set.
|
||||
* This method initializes the Prefix Info option with proper type and length and sets all other fields to zero.
|
||||
*
|
||||
*/
|
||||
bool GetOnLink(void) const { return (mReserved1 & kOnLinkFlagMask) != 0; }
|
||||
void Init(void);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the on-link flag is set.
|
||||
*
|
||||
* @retval TRUE The on-link flag is set.
|
||||
* @retval FALSE The on-link flag is not set.
|
||||
*
|
||||
*/
|
||||
bool IsOnLinkFlagSet(void) const { return (mFlags & kOnLinkFlagMask) != 0; }
|
||||
|
||||
/**
|
||||
* This method sets the on-link (L) flag.
|
||||
*
|
||||
* @param[in] aOnLink A boolean indicates whether the prefix is on-link or off-link.
|
||||
*
|
||||
*/
|
||||
void SetOnLink(bool aOnLink);
|
||||
void SetOnLinkFlag(void) { mFlags |= kOnLinkFlagMask; }
|
||||
|
||||
/**
|
||||
* This method returns the autonomous address-configuration (A) flag.
|
||||
*
|
||||
* @returns A boolean which indicates whether the A flag is set.
|
||||
* This method clears the on-link (L) flag.
|
||||
*
|
||||
*/
|
||||
bool GetAutoAddrConfig(void) const { return (mReserved1 & kAutoConfigFlagMask) != 0; }
|
||||
void ClearOnLinkFlag(void) { mFlags &= ~kOnLinkFlagMask; }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the autonomous address-configuration (A) flag is set.
|
||||
*
|
||||
* @retval TRUE The auto address-config flag is set.
|
||||
* @retval FALSE The auto address-config flag is not set.
|
||||
*
|
||||
*/
|
||||
bool IsAutoAddrConfigFlagSet(void) const { return (mFlags & kAutoConfigFlagMask) != 0; }
|
||||
|
||||
/**
|
||||
* This method sets the autonomous address-configuration (A) flag.
|
||||
*
|
||||
* @param[in] aAutoAddrConfig A boolean indicates whether this prefix can be used
|
||||
* for SLAAC.
|
||||
*
|
||||
*/
|
||||
void SetAutoAddrConfig(bool aAutoAddrConfig);
|
||||
void SetAutoAddrConfigFlag(void) { mFlags |= kAutoConfigFlagMask; }
|
||||
|
||||
/**
|
||||
* This method set the valid lifetime of the prefix in seconds.
|
||||
* This method clears the autonomous address-configuration (A) flag.
|
||||
*
|
||||
*/
|
||||
void ClearAutoAddrConfigFlag(void) { mFlags &= ~kAutoConfigFlagMask; }
|
||||
|
||||
/**
|
||||
* This method sets the valid lifetime of the prefix in seconds.
|
||||
*
|
||||
* @param[in] aValidLifetime The valid lifetime in seconds.
|
||||
*
|
||||
@@ -223,7 +225,7 @@ public:
|
||||
void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
|
||||
|
||||
/**
|
||||
* THis method returns the valid lifetime of the prefix in seconds.
|
||||
* THis method gets the valid lifetime of the prefix in seconds.
|
||||
*
|
||||
* @returns The valid lifetime in seconds.
|
||||
*
|
||||
@@ -255,31 +257,52 @@ public:
|
||||
void SetPrefix(const Ip6::Prefix &aPrefix);
|
||||
|
||||
/**
|
||||
* This method returns the prefix in this option.
|
||||
* This method gets the prefix in this option.
|
||||
*
|
||||
* @returns The IPv6 prefix in this option.
|
||||
* @param[out] aPrefix Reference to an `Ip6::Prefix` to return the prefix.
|
||||
*
|
||||
*/
|
||||
Ip6::Prefix GetPrefix(void) const;
|
||||
void GetPrefix(Ip6::Prefix &aPrefix) const;
|
||||
|
||||
/**
|
||||
* This method tells whether this option is valid.
|
||||
* This method indicates whether or not the option is valid.
|
||||
*
|
||||
* @returns A boolean indicates whether this option is valid.
|
||||
* @retval TRUE The option is valid
|
||||
* @retval FALSE The option is not valid.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const
|
||||
{
|
||||
return (GetSize() == sizeof(*this)) && (mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT) &&
|
||||
(GetPreferredLifetime() <= GetValidLifetime());
|
||||
}
|
||||
bool IsValid(void) const;
|
||||
|
||||
PrefixInfoOption(void) = delete;
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kAutoConfigFlagMask = 0x40; // Bit mask of the Automatic Address Configure flag.
|
||||
static constexpr uint8_t kOnLinkFlagMask = 0x80; // Bit mask of the On-link flag.
|
||||
// Prefix Information Option
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Type | Length | Prefix Length |L|A| Reserved1 |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Valid Lifetime |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Preferred Lifetime |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Reserved2 |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// + +
|
||||
// | |
|
||||
// + Prefix +
|
||||
// | |
|
||||
// + +
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
static constexpr uint8_t kAutoConfigFlagMask = 0x40; // Autonomous address-configuration flag.
|
||||
static constexpr uint8_t kOnLinkFlagMask = 0x80; // On-link flag.
|
||||
|
||||
uint8_t mPrefixLength; // The prefix length in bits.
|
||||
uint8_t mReserved1; // The reserved field.
|
||||
uint8_t mFlags; // The flags field.
|
||||
uint32_t mValidLifetime; // The valid lifetime of the prefix.
|
||||
uint32_t mPreferredLifetime; // The preferred lifetime of the prefix.
|
||||
uint32_t mReserved2; // The reserved field.
|
||||
@@ -291,25 +314,23 @@ static_assert(sizeof(PrefixInfoOption) == 32, "invalid PrefixInfoOption structur
|
||||
/**
|
||||
* This class represents the Route Information Option.
|
||||
*
|
||||
* See section 2.3 of RFC 4191 for definition of this option.
|
||||
* https://tools.ietf.org/html/rfc4191#section-2.3
|
||||
* See section 2.3 of RFC 4191 for definition of this option. [https://tools.ietf.org/html/rfc4191#section-2.3]
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class RouteInfoOption : public Option
|
||||
class RouteInfoOption : public Option, private Clearable<RouteInfoOption>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This type represents a route preference.
|
||||
*
|
||||
*/
|
||||
typedef NetworkData::RoutePreference RoutePreference;
|
||||
static constexpr uint16_t kMinSize = kLengthUnit; ///< Minimum size (in bytes) of a Route Info Option
|
||||
static constexpr Type kType = Type::kRouteInfo; ///< Route Information Option Type.
|
||||
|
||||
typedef NetworkData::RoutePreference RoutePreference; ///< Route Preference
|
||||
|
||||
/**
|
||||
* This constructor initializes this option with zero prefix length.
|
||||
* This method initializes the option setting the type and clearing (setting to zero) all other fields.
|
||||
*
|
||||
*/
|
||||
RouteInfoOption(void);
|
||||
void Init(void);
|
||||
|
||||
/**
|
||||
* This method sets the route preference.
|
||||
@@ -320,7 +341,7 @@ public:
|
||||
void SetPreference(RoutePreference aPreference);
|
||||
|
||||
/**
|
||||
* This method returns the route preference.
|
||||
* This method gets the route preference.
|
||||
*
|
||||
* @returns The route preference.
|
||||
*
|
||||
@@ -336,7 +357,7 @@ public:
|
||||
void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = HostSwap32(aLifetime); }
|
||||
|
||||
/**
|
||||
* This method returns Route Lifetime in seconds.
|
||||
* This method gets Route Lifetime in seconds.
|
||||
*
|
||||
* @returns The Route Lifetime in seconds.
|
||||
*
|
||||
@@ -344,7 +365,7 @@ public:
|
||||
uint32_t GetRouteLifetime(void) const { return HostSwap32(mRouteLifetime); }
|
||||
|
||||
/**
|
||||
* This method sets the prefix.
|
||||
* This method sets the prefix and adjusts the option length based on the prefix length.
|
||||
*
|
||||
* @param[in] aPrefix The prefix contained in this option.
|
||||
*
|
||||
@@ -352,12 +373,12 @@ public:
|
||||
void SetPrefix(const Ip6::Prefix &aPrefix);
|
||||
|
||||
/**
|
||||
* This method returns the prefix in this option.
|
||||
* This method gets the prefix in this option.
|
||||
*
|
||||
* @returns The IPv6 prefix in this option.
|
||||
* @param[out] aPrefix Reference to an `Ip6::Prefix` to return the prefix.
|
||||
*
|
||||
*/
|
||||
Ip6::Prefix GetPrefix(void) const;
|
||||
void GetPrefix(Ip6::Prefix &aPrefix) const;
|
||||
|
||||
/**
|
||||
* This method tells whether this option is valid.
|
||||
@@ -367,17 +388,63 @@ public:
|
||||
*/
|
||||
bool IsValid(void) const;
|
||||
|
||||
/**
|
||||
* This static method calculates the minimum option length for a given prefix length.
|
||||
*
|
||||
* The option length (which is in unit of 8 octets) can be 1, 2, or 3 depending on the prefix length. It can be 1
|
||||
* for a zero prefix length, 2 if the prefix length is not greater than 64, and 3 otherwise.
|
||||
*
|
||||
* @param[in] aPrefixLength The prefix length (in bits).
|
||||
*
|
||||
* @returns The option length (in unit of 8 octet) for @p aPrefixLength.
|
||||
*
|
||||
*/
|
||||
static uint8_t OptionLengthForPrefix(uint8_t aPrefixLength);
|
||||
|
||||
/**
|
||||
* This static method calculates the minimum option size (in bytes) for a given prefix length.
|
||||
*
|
||||
* @param[in] aPrefixLength The prefix length (in bits).
|
||||
*
|
||||
* @returns The option size (in bytes) for @p aPrefixLength.
|
||||
*
|
||||
*/
|
||||
static uint16_t OptionSizeForPrefix(uint8_t aPrefixLength)
|
||||
{
|
||||
return kLengthUnit * OptionLengthForPrefix(aPrefixLength);
|
||||
}
|
||||
|
||||
RouteInfoOption(void) = delete;
|
||||
|
||||
private:
|
||||
// Route Information Option
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Type | Length | Prefix Length |Resvd|Prf|Resvd|
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Route Lifetime |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Prefix (Variable Length) |
|
||||
// . .
|
||||
// . .
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
static constexpr uint8_t kPreferenceOffset = 3;
|
||||
static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset;
|
||||
|
||||
uint8_t mPrefixLength; // The prefix length in bits.
|
||||
uint8_t mReserved; // The reserved field.
|
||||
uint32_t mRouteLifetime; // The lifetime in seconds.
|
||||
Ip6::Address mPrefix; // The prefix.
|
||||
uint8_t * GetPrefixBytes(void) { return AsNonConst(AsConst(this)->GetPrefixBytes()); }
|
||||
const uint8_t *GetPrefixBytes(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
|
||||
|
||||
uint8_t mPrefixLength; // The prefix length in bits.
|
||||
uint8_t mResvdPrf; // The preference.
|
||||
uint32_t mRouteLifetime; // The lifetime in seconds.
|
||||
// Followed by prefix bytes (variable length).
|
||||
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
static_assert(sizeof(RouteInfoOption) == 24, "invalid RouteInfoOption structure");
|
||||
static_assert(sizeof(RouteInfoOption) == 8, "invalid RouteInfoOption structure");
|
||||
|
||||
/**
|
||||
* This class implements the Router Advertisement message.
|
||||
@@ -501,9 +568,7 @@ private:
|
||||
static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure");
|
||||
|
||||
} // namespace RouterAdv
|
||||
|
||||
} // namespace BorderRouter
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
@@ -844,19 +844,21 @@ void RoutingManager::SendRouterAdvertisement(const OmrPrefixArray &aNewOmrPrefix
|
||||
|
||||
if (aNewOnLinkPrefix != nullptr)
|
||||
{
|
||||
RouterAdv::PrefixInfoOption *pio;
|
||||
|
||||
OT_ASSERT(aNewOnLinkPrefix == &mLocalOnLinkPrefix);
|
||||
OT_ASSERT(bufferLength + sizeof(RouterAdv::PrefixInfoOption) <= sizeof(buffer));
|
||||
|
||||
RouterAdv::PrefixInfoOption pio;
|
||||
pio = reinterpret_cast<RouterAdv::PrefixInfoOption *>(buffer + bufferLength);
|
||||
|
||||
pio.SetOnLink(true);
|
||||
pio.SetAutoAddrConfig(true);
|
||||
pio.SetValidLifetime(kDefaultOnLinkPrefixLifetime);
|
||||
pio.SetPreferredLifetime(kDefaultOnLinkPrefixLifetime);
|
||||
pio.SetPrefix(*aNewOnLinkPrefix);
|
||||
pio->Init();
|
||||
pio->SetOnLinkFlag();
|
||||
pio->SetAutoAddrConfigFlag();
|
||||
pio->SetValidLifetime(kDefaultOnLinkPrefixLifetime);
|
||||
pio->SetPreferredLifetime(kDefaultOnLinkPrefixLifetime);
|
||||
pio->SetPrefix(*aNewOnLinkPrefix);
|
||||
|
||||
OT_ASSERT(bufferLength + pio.GetSize() <= sizeof(buffer));
|
||||
memcpy(buffer + bufferLength, &pio, pio.GetSize());
|
||||
bufferLength += pio.GetSize();
|
||||
bufferLength += pio->GetSize();
|
||||
|
||||
if (!mIsAdvertisingLocalOnLinkPrefix)
|
||||
{
|
||||
@@ -865,28 +867,31 @@ void RoutingManager::SendRouterAdvertisement(const OmrPrefixArray &aNewOmrPrefix
|
||||
}
|
||||
|
||||
LogInfo("Send on-link prefix %s in PIO (preferred lifetime = %u seconds, valid lifetime = %u seconds)",
|
||||
aNewOnLinkPrefix->ToString().AsCString(), pio.GetPreferredLifetime(), pio.GetValidLifetime());
|
||||
aNewOnLinkPrefix->ToString().AsCString(), pio->GetPreferredLifetime(), pio->GetValidLifetime());
|
||||
|
||||
mTimeAdvertisedOnLinkPrefix = TimerMilli::GetNow();
|
||||
}
|
||||
else if (mOnLinkPrefixDeprecateTimer.IsRunning())
|
||||
{
|
||||
RouterAdv::PrefixInfoOption pio;
|
||||
RouterAdv::PrefixInfoOption *pio;
|
||||
|
||||
pio.SetOnLink(true);
|
||||
pio.SetAutoAddrConfig(true);
|
||||
pio.SetValidLifetime(TimeMilli::MsecToSec(mOnLinkPrefixDeprecateTimer.GetFireTime() - TimerMilli::GetNow()));
|
||||
OT_ASSERT(bufferLength + sizeof(RouterAdv::PrefixInfoOption) <= sizeof(buffer));
|
||||
|
||||
pio = reinterpret_cast<RouterAdv::PrefixInfoOption *>(buffer + bufferLength);
|
||||
|
||||
pio->Init();
|
||||
pio->SetOnLinkFlag();
|
||||
pio->SetAutoAddrConfigFlag();
|
||||
pio->SetValidLifetime(TimeMilli::MsecToSec(mOnLinkPrefixDeprecateTimer.GetFireTime() - TimerMilli::GetNow()));
|
||||
|
||||
// Set zero preferred lifetime to immediately deprecate the advertised on-link prefix.
|
||||
pio.SetPreferredLifetime(0);
|
||||
pio.SetPrefix(mLocalOnLinkPrefix);
|
||||
pio->SetPreferredLifetime(0);
|
||||
pio->SetPrefix(mLocalOnLinkPrefix);
|
||||
|
||||
OT_ASSERT(bufferLength + pio.GetSize() <= sizeof(buffer));
|
||||
memcpy(buffer + bufferLength, &pio, pio.GetSize());
|
||||
bufferLength += pio.GetSize();
|
||||
bufferLength += pio->GetSize();
|
||||
|
||||
LogInfo("Send on-link prefix %s in PIO (preferred lifetime = %u seconds, valid lifetime = %u seconds)",
|
||||
mLocalOnLinkPrefix.ToString().AsCString(), pio.GetPreferredLifetime(), pio.GetValidLifetime());
|
||||
mLocalOnLinkPrefix.ToString().AsCString(), pio->GetPreferredLifetime(), pio->GetValidLifetime());
|
||||
}
|
||||
|
||||
// Invalidate the advertised OMR prefixes if they are no longer in the new OMR prefix array.
|
||||
@@ -895,15 +900,19 @@ void RoutingManager::SendRouterAdvertisement(const OmrPrefixArray &aNewOmrPrefix
|
||||
{
|
||||
if (!aNewOmrPrefixes.Contains(advertisedOmrPrefix))
|
||||
{
|
||||
RouterAdv::RouteInfoOption rio;
|
||||
RouterAdv::RouteInfoOption *rio;
|
||||
|
||||
OT_ASSERT(bufferLength + RouterAdv::RouteInfoOption::OptionSizeForPrefix(advertisedOmrPrefix.GetLength()) <=
|
||||
sizeof(buffer));
|
||||
|
||||
rio = reinterpret_cast<RouterAdv::RouteInfoOption *>(buffer + bufferLength);
|
||||
|
||||
// Set zero route lifetime to immediately invalidate the advertised OMR prefix.
|
||||
rio.SetRouteLifetime(0);
|
||||
rio.SetPrefix(advertisedOmrPrefix);
|
||||
rio->Init();
|
||||
rio->SetRouteLifetime(0);
|
||||
rio->SetPrefix(advertisedOmrPrefix);
|
||||
|
||||
OT_ASSERT(bufferLength + rio.GetSize() <= sizeof(buffer));
|
||||
memcpy(buffer + bufferLength, &rio, rio.GetSize());
|
||||
bufferLength += rio.GetSize();
|
||||
bufferLength += rio->GetSize();
|
||||
|
||||
LogInfo("Stop advertising OMR prefix %s on interface %u", advertisedOmrPrefix.ToString().AsCString(),
|
||||
mInfraIfIndex);
|
||||
@@ -912,14 +921,18 @@ void RoutingManager::SendRouterAdvertisement(const OmrPrefixArray &aNewOmrPrefix
|
||||
|
||||
for (const Ip6::Prefix &newOmrPrefix : aNewOmrPrefixes)
|
||||
{
|
||||
RouterAdv::RouteInfoOption rio;
|
||||
RouterAdv::RouteInfoOption *rio;
|
||||
|
||||
rio.SetRouteLifetime(kDefaultOmrPrefixLifetime);
|
||||
rio.SetPrefix(newOmrPrefix);
|
||||
OT_ASSERT(bufferLength + RouterAdv::RouteInfoOption::OptionSizeForPrefix(newOmrPrefix.GetLength()) <=
|
||||
sizeof(buffer));
|
||||
|
||||
OT_ASSERT(bufferLength + rio.GetSize() <= sizeof(buffer));
|
||||
memcpy(buffer + bufferLength, &rio, rio.GetSize());
|
||||
bufferLength += rio.GetSize();
|
||||
rio = reinterpret_cast<RouterAdv::RouteInfoOption *>(buffer + bufferLength);
|
||||
|
||||
rio->Init();
|
||||
rio->SetRouteLifetime(kDefaultOmrPrefixLifetime);
|
||||
rio->SetPrefix(newOmrPrefix);
|
||||
|
||||
bufferLength += rio->GetSize();
|
||||
|
||||
LogInfo("Send OMR prefix %s in RIO (valid lifetime = %u seconds)", newOmrPrefix.ToString().AsCString(),
|
||||
kDefaultOmrPrefixLifetime);
|
||||
@@ -969,7 +982,11 @@ bool RoutingManager::IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix)
|
||||
|
||||
bool RoutingManager::IsValidOnLinkPrefix(const RouterAdv::PrefixInfoOption &aPio)
|
||||
{
|
||||
return IsValidOnLinkPrefix(aPio.GetPrefix()) && aPio.GetOnLink() && aPio.GetAutoAddrConfig();
|
||||
Ip6::Prefix prefix;
|
||||
|
||||
aPio.GetPrefix(prefix);
|
||||
|
||||
return IsValidOnLinkPrefix(prefix) && aPio.IsOnLinkFlagSet() && aPio.IsAutoAddrConfigFlagSet();
|
||||
}
|
||||
|
||||
bool RoutingManager::IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix)
|
||||
@@ -1214,11 +1231,13 @@ exit:
|
||||
// routing policy evaluation.
|
||||
bool RoutingManager::UpdateDiscoveredOnLinkPrefix(const RouterAdv::PrefixInfoOption &aPio)
|
||||
{
|
||||
Ip6::Prefix prefix = aPio.GetPrefix();
|
||||
Ip6::Prefix prefix;
|
||||
bool needReevaluate = false;
|
||||
ExternalPrefix onLinkPrefix;
|
||||
ExternalPrefix *existingPrefix = nullptr;
|
||||
|
||||
aPio.GetPrefix(prefix);
|
||||
|
||||
if (!IsValidOnLinkPrefix(aPio))
|
||||
{
|
||||
LogInfo("Ignore invalid on-link prefix in PIO: %s", prefix.ToString().AsCString());
|
||||
@@ -1307,10 +1326,12 @@ exit:
|
||||
// from the Thread network).
|
||||
void RoutingManager::UpdateDiscoveredOmrPrefix(const RouterAdv::RouteInfoOption &aRio)
|
||||
{
|
||||
Ip6::Prefix prefix = aRio.GetPrefix();
|
||||
Ip6::Prefix prefix;
|
||||
ExternalPrefix omrPrefix;
|
||||
ExternalPrefix *existingPrefix = nullptr;
|
||||
|
||||
aRio.GetPrefix(prefix);
|
||||
|
||||
if (!IsValidOmrPrefix(prefix))
|
||||
{
|
||||
LogInfo("Ignore invalid OMR prefix in RIO: %s", prefix.ToString().AsCString());
|
||||
|
||||
@@ -67,6 +67,14 @@
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 1
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
*
|
||||
* Define to 1 to enable Border Routing support.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 1
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user