diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 453f4954917..97fbad55fe0 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -593,6 +593,7 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode) // RA message max length is derived to accommodate: // // - The RA header. + // - One RA Flags Extensions Option (with stub router flag). // - One PIO for current local on-link prefix. // - At most `kMaxOldPrefixes` for old deprecating on-link prefixes. // - At most twice `kMaxOnMeshPrefixes` RIO for on-mesh prefixes. @@ -600,8 +601,8 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode) // previous prefixes while adding new ones. static constexpr uint16_t kMaxRaLength = - sizeof(Ip6::Nd::RouterAdvertMessage::Header) + sizeof(Ip6::Nd::PrefixInfoOption) + - sizeof(Ip6::Nd::PrefixInfoOption) * OnLinkPrefixManager::kMaxOldPrefixes + + sizeof(Ip6::Nd::RouterAdvertMessage::Header) + sizeof(Ip6::Nd::RaFlagsExtOption) + + sizeof(Ip6::Nd::PrefixInfoOption) + sizeof(Ip6::Nd::PrefixInfoOption) * OnLinkPrefixManager::kMaxOldPrefixes + 2 * kMaxOnMeshPrefixes * (sizeof(Ip6::Nd::RouteInfoOption) + sizeof(Ip6::Prefix)); uint8_t buffer[kMaxRaLength]; @@ -611,6 +612,11 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode) LogInfo("Preparing RA"); +#if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE + SuccessOrAssert(raMsg.AppendFlagsExtensionOption(/* aStubRouterFlag */ true)); + LogInfo("- FlagsExt - StubRouter:1"); +#endif + // Append PIO for local on-link prefix if is either being // advertised or deprecated and for old prefix if is being // deprecated. diff --git a/src/core/config/border_routing.h b/src/core/config/border_routing.h index a7f57d1fedd..4640a081acd 100644 --- a/src/core/config/border_routing.h +++ b/src/core/config/border_routing.h @@ -126,6 +126,17 @@ #define OPENTHREAD_CONFIG_BORDER_ROUTING_ROUTER_ACTIVE_CHECK_TIMEOUT (60 * 1000) // (in msec). #endif +/** + * @def OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE + * + * Define to 1 so for the routing manager to include the Flags Extension Option with Stub Router flag in the emitted + * Router Advertisement messages from this Border Router. + * + */ +#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE +#define OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE 1 +#endif + /** * @def OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE * diff --git a/src/core/net/nd6.cpp b/src/core/net/nd6.cpp index 3d24b6ad70d..e66fb043f67 100644 --- a/src/core/net/nd6.cpp +++ b/src/core/net/nd6.cpp @@ -269,6 +269,25 @@ Error RouterAdvertMessage::AppendRouteInfoOption(const Prefix &aPrefix, return error; } +Error RouterAdvertMessage::AppendFlagsExtensionOption(bool aStubRouterFlag) +{ + Error error = kErrorNone; + RaFlagsExtOption *flagsOption; + + flagsOption = static_cast(AppendOption(sizeof(RaFlagsExtOption))); + VerifyOrExit(flagsOption != nullptr, error = kErrorNoBufs); + + flagsOption->Init(); + + if (aStubRouterFlag) + { + flagsOption->SetStubRouterFlag(); + } + +exit: + return error; +} + //---------------------------------------------------------------------------------------------------------------------- // RouterSolicitMessage diff --git a/src/core/net/nd6.hpp b/src/core/net/nd6.hpp index bc116a450af..bbf6a6ea78f 100644 --- a/src/core/net/nd6.hpp +++ b/src/core/net/nd6.hpp @@ -761,6 +761,17 @@ class RouterAdvertMessage */ Error AppendRouteInfoOption(const Prefix &aPrefix, uint32_t aRouteLifetime, RoutePreference aPreference); + /** + * Appends a Flags Extension Option to the RA message. + * + * @param[in] aStubRouterFlag The stub router flag. + * + * @retval kErrorNone Option is appended successfully. + * @retval kErrorNoBufs No more space in the buffer to append the option. + * + */ + Error AppendFlagsExtensionOption(bool aStubRouterFlag); + /** * Indicates whether or not the RA message contains any options. * diff --git a/tests/unit/test_routing_manager.cpp b/tests/unit/test_routing_manager.cpp index ae1d21e7b75..c5cbb5cdad6 100644 --- a/tests/unit/test_routing_manager.cpp +++ b/tests/unit/test_routing_manager.cpp @@ -449,6 +449,17 @@ void ValidateRouterAdvert(const Icmp6Packet &aPacket) break; } +#if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE + case Ip6::Nd::Option::kTypeRaFlagsExtension: + { + const Ip6::Nd::RaFlagsExtOption &flagsOption = static_cast(option); + + VerifyOrQuit(flagsOption.IsValid()); + VerifyOrQuit(flagsOption.IsStubRouterFlagSet()); + break; + } +#endif + default: VerifyOrQuit(false, "Unexpected option type in RA msg"); } @@ -545,6 +556,15 @@ void LogRouterAdvert(const Icmp6Packet &aPacket) break; } + case Ip6::Nd::Option::kTypeRaFlagsExtension: + { + const Ip6::Nd::RaFlagsExtOption &flagsOption = static_cast(option); + + VerifyOrQuit(flagsOption.IsValid()); + Log(" FlagsExt - StubRouter:%u", flagsOption.IsStubRouterFlagSet()); + break; + } + default: VerifyOrQuit(false, "Bad option type in RA msg"); }