diff --git a/src/core/border_router/router_advertisement.cpp b/src/core/border_router/router_advertisement.cpp index 66dbdd5dd..d2356c562 100644 --- a/src/core/border_router/router_advertisement.cpp +++ b/src/core/border_router/router_advertisement.cpp @@ -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(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 diff --git a/src/core/border_router/router_advertisement.hpp b/src/core/border_router/router_advertisement.hpp index 060383b7b..2ca972c3a 100644 --- a/src/core/border_router/router_advertisement.hpp +++ b/src/core/border_router/router_advertisement.hpp @@ -46,6 +46,7 @@ #include #include +#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((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 { 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 { 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(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 diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 5f1884e38..6f1ae4a98 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -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(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(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(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(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()); diff --git a/tests/toranj/openthread-core-toranj-config.h b/tests/toranj/openthread-core-toranj-config.h index c04317d7f..7a180cc3e 100644 --- a/tests/toranj/openthread-core-toranj-config.h +++ b/tests/toranj/openthread-core-toranj-config.h @@ -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 *