[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.
This commit is contained in:
kangping
2021-04-20 08:00:55 -07:00
committed by GitHub
parent 33012716ee
commit 4e20dff989
10 changed files with 87 additions and 130 deletions
+6 -11
View File
@@ -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.
+1 -1
View File
@@ -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
+17 -8
View File
@@ -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"
+2 -6
View File
@@ -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<Instance *>(aInstance);
return instance.Get<BorderRouter::RoutingManager>().Init(
aInfraIfIndex, aInfraIfIsRunning, static_cast<const Ip6::Address *>(aInfraIfLinkLocalAddress));
return instance.Get<BorderRouter::RoutingManager>().Init(aInfraIfIndex, aInfraIfIsRunning);
}
otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled)
+2 -6
View File
@@ -53,15 +53,11 @@ extern "C" void otPlatInfraIfRecvIcmp6Nd(otInstance * aInstance,
aInfraIfIndex, static_cast<const Ip6::Address &>(*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<Instance *>(aInstance);
return instance.Get<BorderRouter::RoutingManager>().HandleInfraIfStateChanged(
aInfraIfIndex, aIsRunning, static_cast<const Ip6::Address *>(aLinkLocalAddress));
return instance.Get<BorderRouter::RoutingManager>().HandleInfraIfStateChanged(aInfraIfIndex, aIsRunning);
}
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+8 -25
View File
@@ -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<Mle::MleRouter>().IsAttached() && mInfraIfIsRunning && mInfraIfLinkLocalAddress.IsLinkLocal())
if (mIsEnabled && Get<Mle::MleRouter>().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<const Ip6::Address *>(&mInfraIfLinkLocalAddress);
VerifyOrExit(aBuffer != nullptr && aBufferLength >= sizeof(*icmp6Header), error = kErrorParse);
icmp6Header = reinterpret_cast<const Ip6::Icmp::Header *>(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:
+12 -23
View File
@@ -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;
+38 -40
View File
@@ -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<sockaddr_in6 *>(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<sockaddr_in6 *>(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:
{
-8
View File
@@ -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.
*
+1 -2
View File
@@ -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