[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:
Abtin Keshavarzian
2022-05-17 15:39:15 -07:00
committed by GitHub
parent cb41668c0c
commit 25c610a0ed
4 changed files with 287 additions and 192 deletions
+67 -66
View File
@@ -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
+156 -91
View File
@@ -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
+56 -35
View File
@@ -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
*