From 4e20dff989a6c11fdc7f3b805542752731b28de2 Mon Sep 17 00:00:00 2001 From: kangping Date: Tue, 20 Apr 2021 23:00:55 +0800 Subject: [PATCH] [border-router] add platform API otPlatInfraIfHasAddress (#6430) This commit removes the need of getting LLA of infra interface but adds a new platform API otPlatInfraIfHasAddress which matches the infra interface and a given address. Background: The infra interface LLA is used in the Routing Manager for only testing if RA/RS message is initiated from the infra interface. --- include/openthread/border_router.h | 17 ++--- include/openthread/instance.h | 2 +- include/openthread/platform/infra_if.h | 25 +++++-- src/core/api/border_router_api.cpp | 8 +- src/core/border_router/infra_if_platform.cpp | 8 +- src/core/border_router/routing_manager.cpp | 33 ++------- src/core/border_router/routing_manager.hpp | 35 +++------ src/posix/platform/infra_if.cpp | 78 ++++++++++---------- src/posix/platform/platform-posix.h | 8 -- src/posix/platform/system.cpp | 3 +- 10 files changed, 87 insertions(+), 130 deletions(-) diff --git a/include/openthread/border_router.h b/include/openthread/border_router.h index c1e489123..2b6d3f413 100644 --- a/include/openthread/border_router.h +++ b/include/openthread/border_router.h @@ -57,25 +57,20 @@ extern "C" { * * @note This method MUST be called before any other otBorderRouting* APIs. * - * @param[in] aInstance A pointer to an OpenThread instance. - * @param[in] aInfraIfIndex The infrastructure interface index. - * @param[in] aInfraIfIsRunning A boolean that indicates whether the infrastructure - * interface is running. - * @param[in] aInfraIfLinkLocalAddress A pointer to the IPv6 link-local address of the infrastructure - * interface. NULL if the IPv6 link-local address is missing. + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aInfraIfIndex The infrastructure interface index. + * @param[in] aInfraIfIsRunning A boolean that indicates whether the infrastructure + * interface is running. * * @retval OT_ERROR_NONE Successfully started the Border Routing Manager on given infrastructure. * @retval OT_ERROR_INVALID_STATE The Border Routing Manager has already been initialized. - * @retval OT_ERROR_INVALID_ARGS The index or the IPv6 link-local address of the infra interface is not valid. + * @retval OT_ERROR_INVALID_ARGS The index of the infrastructure interface is not valid. * @retval OT_ERROR_FAILED Internal failure. Usually due to failure in generating random prefixes. * * @sa otPlatInfraIfStateChanged. * */ -otError otBorderRoutingInit(otInstance * aInstance, - uint32_t aInfraIfIndex, - bool aInfraIfIsRunning, - const otIp6Address *aInfraIfLinkLocalAddress); +otError otBorderRoutingInit(otInstance *aInstance, uint32_t aInfraIfIndex, bool aInfraIfIsRunning); /** * This method enables/disables the Border Routing Manager. diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 3f62f2915..a45f5ecc0 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (101) +#define OPENTHREAD_API_VERSION (102) /** * @addtogroup api-instance diff --git a/include/openthread/platform/infra_if.h b/include/openthread/platform/infra_if.h index d052eb2ac..41b916980 100644 --- a/include/openthread/platform/infra_if.h +++ b/include/openthread/platform/infra_if.h @@ -46,6 +46,17 @@ extern "C" { #endif +/** + * This method tells whether an infra interface has the given IPv6 address assigned. + * + * @param[in] aInfraIfIndex The index of the infra interface. + * @param[in] aAddress The IPv6 address. + * + * @returns TRUE if the infra interface has given IPv6 address assigned, FALSE otherwise. + * + */ +bool otPlatInfraIfHasAddress(uint32_t aInfraIfIndex, const otIp6Address *aAddress); + /** * This method sends an ICMPv6 Neighbor Discovery message on given infrastructure interface. * @@ -94,24 +105,22 @@ extern void otPlatInfraIfRecvIcmp6Nd(otInstance * aInstance, * The infra interface driver calls this method to notify OpenThread * of the interface state changes. * + * It is fine for the platform to call to method even when the running state + * of the interface hasn't changed. In this case, the Routing Manager state is + * not affected. + * * @param[in] aInstance The OpenThread instance structure. * @param[in] aInfraIfIndex The index of the infrastructure interface. * @param[in] aIsRunning A boolean that indicates whether the infrastructure * interface is running. - * @param[in] aLinkLocalAddress A pointer to the IPv6 link-local address of the infrastructure - * interface. NULL if the IPv6 link-local address is lost. * * @retval OT_ERROR_NONE Successfully updated the infra interface status. * @retval OT_ERROR_INVALID_STATE The Routing Manager is not initialized. * @retval OT_ERROR_INVALID_ARGS The @p aInfraIfIndex doesn't match the infra interface the - * Routing Manager are initialized with, or the @p aLinkLocalAddress - * is not a valid IPv6 link-local address. + * Routing Manager are initialized with. * */ -extern otError otPlatInfraIfStateChanged(otInstance * aInstance, - uint32_t aInfraIfIndex, - bool aIsRunning, - const otIp6Address *aLinkLocalAddress); +extern otError otPlatInfraIfStateChanged(otInstance *aInstance, uint32_t aInfraIfIndex, bool aIsRunning); #ifdef __cplusplus } // extern "C" diff --git a/src/core/api/border_router_api.cpp b/src/core/api/border_router_api.cpp index a72530967..3135fc116 100644 --- a/src/core/api/border_router_api.cpp +++ b/src/core/api/border_router_api.cpp @@ -44,15 +44,11 @@ using namespace ot; #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE -otError otBorderRoutingInit(otInstance * aInstance, - uint32_t aInfraIfIndex, - bool aInfraIfIsRunning, - const otIp6Address *aInfraIfLinkLocalAddress) +otError otBorderRoutingInit(otInstance *aInstance, uint32_t aInfraIfIndex, bool aInfraIfIsRunning) { Instance &instance = *static_cast(aInstance); - return instance.Get().Init( - aInfraIfIndex, aInfraIfIsRunning, static_cast(aInfraIfLinkLocalAddress)); + return instance.Get().Init(aInfraIfIndex, aInfraIfIsRunning); } otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled) diff --git a/src/core/border_router/infra_if_platform.cpp b/src/core/border_router/infra_if_platform.cpp index 8a0d783be..726e358f1 100644 --- a/src/core/border_router/infra_if_platform.cpp +++ b/src/core/border_router/infra_if_platform.cpp @@ -53,15 +53,11 @@ extern "C" void otPlatInfraIfRecvIcmp6Nd(otInstance * aInstance, aInfraIfIndex, static_cast(*aSrcAddress), aBuffer, aBufferLength); } -extern "C" otError otPlatInfraIfStateChanged(otInstance * aInstance, - uint32_t aInfraIfIndex, - bool aIsRunning, - const otIp6Address *aLinkLocalAddress) +extern "C" otError otPlatInfraIfStateChanged(otInstance *aInstance, uint32_t aInfraIfIndex, bool aIsRunning) { Instance &instance = *static_cast(aInstance); - return instance.Get().HandleInfraIfStateChanged( - aInfraIfIndex, aIsRunning, static_cast(aLinkLocalAddress)); + return instance.Get().HandleInfraIfStateChanged(aInfraIfIndex, aIsRunning); } #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 3bb82d05a..1c2f59326 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -72,8 +72,6 @@ RoutingManager::RoutingManager(Instance &aInstance) , mRouterSolicitCount(0) , mRoutingPolicyTimer(aInstance, HandleRoutingPolicyTimer) { - mInfraIfLinkLocalAddress.Clear(); - mLocalOmrPrefix.Clear(); memset(mAdvertisedOmrPrefixes, 0, sizeof(mAdvertisedOmrPrefixes)); @@ -82,7 +80,7 @@ RoutingManager::RoutingManager(Instance &aInstance) memset(mDiscoveredPrefixes, 0, sizeof(mDiscoveredPrefixes)); } -Error RoutingManager::Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning, const Ip6::Address *aInfraIfLinkLocalAddress) +Error RoutingManager::Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning) { Error error; @@ -95,7 +93,7 @@ Error RoutingManager::Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning, const mInfraIfIndex = aInfraIfIndex; // Initialize the infra interface status. - SuccessOrExit(error = HandleInfraIfStateChanged(mInfraIfIndex, aInfraIfIsRunning, aInfraIfLinkLocalAddress)); + SuccessOrExit(error = HandleInfraIfStateChanged(mInfraIfIndex, aInfraIfIsRunning)); exit: if (error != kErrorNone) @@ -175,7 +173,7 @@ exit: void RoutingManager::EvaluateState(void) { - if (mIsEnabled && Get().IsAttached() && mInfraIfIsRunning && mInfraIfLinkLocalAddress.IsLinkLocal()) + if (mIsEnabled && Get().IsAttached() && mInfraIfIsRunning) { Start(); } @@ -242,13 +240,9 @@ void RoutingManager::RecvIcmp6Message(uint32_t aInfraIfIndex, { Error error = kErrorNone; const Ip6::Icmp::Header *icmp6Header; - const Ip6::Address * infraLinkLocalAddr; VerifyOrExit(IsInitialized() && mIsRunning, error = kErrorDrop); - VerifyOrExit(aInfraIfIndex == mInfraIfIndex, error = kErrorDrop); - infraLinkLocalAddr = static_cast(&mInfraIfLinkLocalAddress); - VerifyOrExit(aBuffer != nullptr && aBufferLength >= sizeof(*icmp6Header), error = kErrorParse); icmp6Header = reinterpret_cast(aBuffer); @@ -260,7 +254,7 @@ void RoutingManager::RecvIcmp6Message(uint32_t aInfraIfIndex, break; case Ip6::Icmp::Header::kTypeRouterSolicit: // Drop Router Solicitations initiated from infra interface. - VerifyOrExit(aSrcAddress != *infraLinkLocalAddr, error = kErrorDrop); + VerifyOrExit(!otPlatInfraIfHasAddress(mInfraIfIndex, &aSrcAddress), error = kErrorDrop); HandleRouterSolicit(aSrcAddress, aBuffer, aBufferLength); break; default: @@ -274,29 +268,18 @@ exit: } } -Error RoutingManager::HandleInfraIfStateChanged(uint32_t aInfraIfIndex, - bool aIsRunning, - const Ip6::Address *aLinkLocalAddress) +Error RoutingManager::HandleInfraIfStateChanged(uint32_t aInfraIfIndex, bool aIsRunning) { Error error = kErrorNone; VerifyOrExit(IsInitialized(), error = kErrorInvalidState); VerifyOrExit(aInfraIfIndex == mInfraIfIndex, error = kErrorInvalidArgs); - VerifyOrExit(aLinkLocalAddress == nullptr || aLinkLocalAddress->IsLinkLocal(), error = kErrorInvalidArgs); + VerifyOrExit(aIsRunning != mInfraIfIsRunning); - otLogInfoBr("infra interface state changed: %s, link-local-addr=%s", aIsRunning ? "RUNNING" : "NOT RUNNING", - (aLinkLocalAddress != nullptr) ? aLinkLocalAddress->ToString().AsCString() : "(null)"); + otLogInfoBr("infra interface (%u) state changed: %sRUNNING -> %sRUNNING", aInfraIfIndex, + (mInfraIfIsRunning ? "" : "NOT "), (aIsRunning ? "" : "NOT ")); mInfraIfIsRunning = aIsRunning; - if (aLinkLocalAddress == nullptr) - { - mInfraIfLinkLocalAddress.Clear(); - } - else - { - mInfraIfLinkLocalAddress = *aLinkLocalAddress; - } - EvaluateState(); exit: diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index 96f942d67..6269495f6 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -85,17 +85,15 @@ public: /** * This method initializes the routing manager on given infrastructure interface. * - * @param[in] aInfraIfIndex An infrastructure network interface index. - * @param[in] aInfraIfIsRunning A boolean that indicates whether the infrastructure - * interface is running. - * @param[in] aInfraIfLinkLocalAddress A pointer to the IPv6 link-local address of the infrastructure - * interface. NULL if the IPv6 link-local address is missing. + * @param[in] aInfraIfIndex An infrastructure network interface index. + * @param[in] aInfraIfIsRunning A boolean that indicates whether the infrastructure + * interface is running. * - * @retval kErrorNone Successfully started the routing manager. - * @retval kErrorInvalidArgs The index of the infra interface is not valid. + * @retval kErrorNone Successfully started the routing manager. + * @retval kErrorInvalidArgs The index of the infra interface is not valid. * */ - Error Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning, const Ip6::Address *aInfraIfLinkLocalAddress); + Error Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning); /** * This method enables/disables the Border Routing Manager. @@ -129,20 +127,17 @@ public: /** * This method handles infrastructure interface state changes. * - * @param[in] aInfraIfIndex The index of the infrastructure interface. - * @param[in] aIsRunning A boolean that indicates whether the infrastructure - * interface is running. - * @param[in] aLinkLocalAddress A pointer to the IPv6 link local address of the infrastructure - * interface. NULL if the IPv6 link local address is lost. + * @param[in] aInfraIfIndex The index of the infrastructure interface. + * @param[in] aIsRunning A boolean that indicates whether the infrastructure + * interface is running. * * @retval kErrorNone Successfully updated the infra interface status. * @retval kErrorInvalidState The Routing Manager is not initialized. - * @retval kErrorInvalidArgs The @p aInfraIfIndex doesn't match the infra interface the Routing Manager are - * initialized with, or the @p aLinkLocalAddress is not a valid IPv6 link-local - * address. + * @retval kErrorInvalidArgs The @p aInfraIfIndex doesn't match the infra interface + * the Routing Manager is initialized with. * */ - Error HandleInfraIfStateChanged(uint32_t aInfraIfIndex, bool aIsRunning, const Ip6::Address *aLinkLocalAddress); + Error HandleInfraIfStateChanged(uint32_t aInfraIfIndex, bool aIsRunning); private: enum : uint16_t @@ -260,12 +255,6 @@ private: // messages will be sent. uint32_t mInfraIfIndex; - // The IPv6 link-local address of the infra interface. It's - // UNSPECIFIED if no valid IPv6 link-local address is associated - // with the infra interface and the Routing Manager will be - // stopped. - Ip6::Address mInfraIfLinkLocalAddress; - // The OMR prefix loaded from local persistent storage or randomly // generated if non is found in persistent storage. Ip6::Prefix mLocalOmrPrefix; diff --git a/src/posix/platform/infra_if.cpp b/src/posix/platform/infra_if.cpp index 17bcaede6..a17110857 100644 --- a/src/posix/platform/infra_if.cpp +++ b/src/posix/platform/infra_if.cpp @@ -59,17 +59,44 @@ #include "common/debug.hpp" #include "lib/platform/exit_code.h" -static char sInfraIfName[IFNAMSIZ]; -static uint32_t sInfraIfIndex = 0; -static int sInfraIfIcmp6Socket = -1; -static int sNetLinkSocket = -1; -static otIp6Address sInfraIfLinkLocalAddr; +static char sInfraIfName[IFNAMSIZ]; +static uint32_t sInfraIfIndex = 0; +static int sInfraIfIcmp6Socket = -1; +static int sNetLinkSocket = -1; static int CreateIcmp6Socket(void); static int CreateNetLinkSocket(void); static void ReceiveNetLinkMessage(otInstance *aInstance); static void ReceiveIcmp6Message(otInstance *aInstance); +bool otPlatInfraIfHasAddress(uint32_t aInfraIfIndex, const otIp6Address *aAddress) +{ + bool ret = false; + struct ifaddrs *ifAddrs = nullptr; + + VerifyOrDie(getifaddrs(&ifAddrs) != -1, OT_EXIT_ERROR_ERRNO); + + for (struct ifaddrs *addr = ifAddrs; addr != nullptr; addr = addr->ifa_next) + { + struct sockaddr_in6 *ip6Addr; + + if (if_nametoindex(addr->ifa_name) != aInfraIfIndex || addr->ifa_addr->sa_family != AF_INET6) + { + continue; + } + + ip6Addr = reinterpret_cast(addr->ifa_addr); + if (memcmp(&ip6Addr->sin6_addr, aAddress, sizeof(*aAddress)) == 0) + { + ExitNow(ret = true); + } + } + +exit: + freeifaddrs(ifAddrs); + return ret; +} + otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex, const otIp6Address *aDestAddress, const uint8_t * aBuffer, @@ -144,37 +171,6 @@ exit: return error; } -const otIp6Address *platformInfraIfGetLinkLocalAddress(void) -{ - const otIp6Address *ret = nullptr; - struct ifaddrs * ifAddrs = nullptr; - - VerifyOrDie(getifaddrs(&ifAddrs) != -1, OT_EXIT_ERROR_ERRNO); - - for (struct ifaddrs *addr = ifAddrs; addr != nullptr; addr = addr->ifa_next) - { - struct sockaddr_in6 *ip6Addr; - - if (strncmp(addr->ifa_name, sInfraIfName, sizeof(sInfraIfName)) != 0 || addr->ifa_addr->sa_family != AF_INET6) - { - continue; - } - - ip6Addr = reinterpret_cast(addr->ifa_addr); - if (IN6_IS_ADDR_LINKLOCAL(&ip6Addr->sin6_addr)) - { - memcpy(&sInfraIfLinkLocalAddr, &ip6Addr->sin6_addr, sizeof(sInfraIfLinkLocalAddr)); - ExitNow(ret = &sInfraIfLinkLocalAddr); - } - } - - otLogWarnPlat("cannot find IPv6 link-local address for interface %s", sInfraIfName); - -exit: - freeifaddrs(ifAddrs); - return ret; -} - bool platformInfraIfIsRunning(void) { int sock; @@ -350,12 +346,14 @@ static void ReceiveNetLinkMessage(otInstance *aInstance) { switch (header->nlmsg_type) { - case RTM_NEWLINK: - case RTM_DELLINK: + // There are no effective netlink message types to get us notified + // of interface RUNNING state changes. But addresses events are + // usually associated with interface state changes. case RTM_NEWADDR: case RTM_DELADDR: - SuccessOrDie(otPlatInfraIfStateChanged(aInstance, sInfraIfIndex, platformInfraIfIsRunning(), - platformInfraIfGetLinkLocalAddress())); + case RTM_NEWLINK: + case RTM_DELLINK: + SuccessOrDie(otPlatInfraIfStateChanged(aInstance, sInfraIfIndex, platformInfraIfIsRunning())); break; case NLMSG_ERROR: { diff --git a/src/posix/platform/platform-posix.h b/src/posix/platform/platform-posix.h index 835bd0ca0..e774653dd 100644 --- a/src/posix/platform/platform-posix.h +++ b/src/posix/platform/platform-posix.h @@ -525,14 +525,6 @@ void platformInfraIfDeinit(void); */ bool platformInfraIfIsRunning(void); -/** - * this function returns the IPv6 link-local address of the infrastructure interface. - * - * @returns A pointer to the link-local address; NULL if no link-local address is present. - * - */ -const otIp6Address *platformInfraIfGetLinkLocalAddress(void); - /** * This function updates the read fd set. * diff --git a/src/posix/platform/system.cpp b/src/posix/platform/system.cpp index 3bb55f99a..af2eea23b 100644 --- a/src/posix/platform/system.cpp +++ b/src/posix/platform/system.cpp @@ -111,8 +111,7 @@ otInstance *otSysInit(otPlatformConfig *aPlatformConfig) infraIfIndex = platformInfraIfInit(instance, aPlatformConfig->mBackboneInterfaceName); - SuccessOrDie(otBorderRoutingInit(instance, infraIfIndex, platformInfraIfIsRunning(), - platformInfraIfGetLinkLocalAddress())); + SuccessOrDie(otBorderRoutingInit(instance, infraIfIndex, platformInfraIfIsRunning())); SuccessOrDie(otBorderRoutingSetEnabled(instance, /* aEnabled */ true)); } #endif