mirror of
https://github.com/espressif/openthread.git
synced 2026-10-01 13:27:42 +00:00
[posix] handle dynamic infra if status (#6186)
This commit includes below changes: - handles dynamic infrastructure interface status changes. The Routing Manager will be started if the infra interface status turns to be RUNNING and a valid link-local address is present. Otherwise, the Routing Manager will be stopped. - changes the default status of the Routing Manager from enabled to disabled and it is initially enabled for the posix platform. - the posix implementation now doesn't require the presence of the link-local address at initialization stage. In this case, the Routing Manager will not be started before a link-local address is added to the infra interface. - add CI tests for the new behavior.
This commit is contained in:
@@ -57,20 +57,30 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* @note This method MUST be called before any other otBorderRouting* APIs.
|
* @note This method MUST be called before any other otBorderRouting* APIs.
|
||||||
*
|
*
|
||||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||||
* @param[in] aInfraIfIndex The infrastructure interface index.
|
* @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.
|
||||||
*
|
*
|
||||||
* @retval OT_ERROR_NONE Successfully started the Border Routing manager on given infrastructure.
|
* @retval OT_ERROR_NONE Successfully started the Border Routing Manager on given infrastructure.
|
||||||
* @retval OT_ERROR_INVALID_ARGS The index of the infra interface is not valid.
|
* @retval OT_ERROR_INVALID_STATE The Border Routing Manager has already been initialized.
|
||||||
* @retval OT_ERROR_FAILED Internal failure. This is usually failed to generate random prefixes.
|
* @retval OT_ERROR_INVALID_ARGS The index or the IPv6 link-local address of the infra 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);
|
otError otBorderRoutingInit(otInstance * aInstance,
|
||||||
|
uint32_t aInfraIfIndex,
|
||||||
|
bool aInfraIfIsRunning,
|
||||||
|
const otIp6Address *aInfraIfLinkLocalAddress);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method enables/disables the Border Routing Manager.
|
* This method enables/disables the Border Routing Manager.
|
||||||
*
|
*
|
||||||
* @note The Border Routing Manager is enabled by default.
|
* @note The Border Routing Manager is disabled by default.
|
||||||
*
|
*
|
||||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||||
* @param[in] aEnabled A boolean to enable/disable the routing manager.
|
* @param[in] aEnabled A boolean to enable/disable the routing manager.
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ extern "C" {
|
|||||||
* @note This number versions both OpenThread platform and user APIs.
|
* @note This number versions both OpenThread platform and user APIs.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#define OPENTHREAD_API_VERSION (79)
|
#define OPENTHREAD_API_VERSION (80)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup api-instance
|
* @addtogroup api-instance
|
||||||
|
|||||||
@@ -46,16 +46,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the IPv6 link-local address of given infrastructure interface.
|
|
||||||
*
|
|
||||||
* @param[in] aInfraIfIndex The index of the infrastructure interface.
|
|
||||||
*
|
|
||||||
* @returns A pointer to the IPv6 link-local address. NULL if no valid IPv6 link-local address found.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
const otIp6Address *otPlatInfraIfGetLinkLocalAddress(uint32_t aInfraIfIndex);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sends an ICMPv6 Neighbor Discovery message on given infrastructure interface.
|
* This method sends an ICMPv6 Neighbor Discovery message on given infrastructure interface.
|
||||||
*
|
*
|
||||||
@@ -100,6 +90,29 @@ extern void otPlatInfraIfRecvIcmp6Nd(otInstance * aInstance,
|
|||||||
const uint8_t * aBuffer,
|
const uint8_t * aBuffer,
|
||||||
uint16_t aBufferLength);
|
uint16_t aBufferLength);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The infra interface driver calls this method to notify OpenThread
|
||||||
|
* of the interface state changes.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
extern otError otPlatInfraIfStateChanged(otInstance * aInstance,
|
||||||
|
uint32_t aInfraIfIndex,
|
||||||
|
bool aIsRunning,
|
||||||
|
const otIp6Address *aLinkLocalAddress);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,11 +44,15 @@
|
|||||||
using namespace ot;
|
using namespace ot;
|
||||||
|
|
||||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||||
otError otBorderRoutingInit(otInstance *aInstance, uint32_t aInfraIfIndex)
|
otError otBorderRoutingInit(otInstance * aInstance,
|
||||||
|
uint32_t aInfraIfIndex,
|
||||||
|
bool aInfraIfIsRunning,
|
||||||
|
const otIp6Address *aInfraIfLinkLocalAddress)
|
||||||
{
|
{
|
||||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||||
|
|
||||||
return instance.Get<BorderRouter::RoutingManager>().Init(aInfraIfIndex);
|
return instance.Get<BorderRouter::RoutingManager>().Init(
|
||||||
|
aInfraIfIndex, aInfraIfIsRunning, static_cast<const Ip6::Address *>(aInfraIfLinkLocalAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled)
|
otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled)
|
||||||
|
|||||||
@@ -52,4 +52,16 @@ extern "C" void otPlatInfraIfRecvIcmp6Nd(otInstance * aInstance,
|
|||||||
instance.Get<BorderRouter::RoutingManager>().RecvIcmp6Message(
|
instance.Get<BorderRouter::RoutingManager>().RecvIcmp6Message(
|
||||||
aInfraIfIndex, static_cast<const Ip6::Address &>(*aSrcAddress), aBuffer, aBufferLength);
|
aInfraIfIndex, static_cast<const Ip6::Address &>(*aSrcAddress), aBuffer, aBufferLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" otError otPlatInfraIfStateChanged(otInstance * aInstance,
|
||||||
|
uint32_t aInfraIfIndex,
|
||||||
|
bool aIsRunning,
|
||||||
|
const otIp6Address *aLinkLocalAddress)
|
||||||
|
{
|
||||||
|
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||||
|
|
||||||
|
return instance.Get<BorderRouter::RoutingManager>().HandleInfraIfStateChanged(
|
||||||
|
aInfraIfIndex, aIsRunning, static_cast<const Ip6::Address *>(aLinkLocalAddress));
|
||||||
|
}
|
||||||
|
|
||||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||||
|
|||||||
@@ -60,8 +60,9 @@ namespace BorderRouter {
|
|||||||
RoutingManager::RoutingManager(Instance &aInstance)
|
RoutingManager::RoutingManager(Instance &aInstance)
|
||||||
: InstanceLocator(aInstance)
|
: InstanceLocator(aInstance)
|
||||||
, mIsRunning(false)
|
, mIsRunning(false)
|
||||||
|
, mIsEnabled(false)
|
||||||
|
, mInfraIfIsRunning(false)
|
||||||
, mInfraIfIndex(0)
|
, mInfraIfIndex(0)
|
||||||
, mEnabled(true) // The routing manager is by default enabled.
|
|
||||||
, mAdvertisedOmrPrefixNum(0)
|
, mAdvertisedOmrPrefixNum(0)
|
||||||
, mAdvertisedOnLinkPrefix(nullptr)
|
, mAdvertisedOnLinkPrefix(nullptr)
|
||||||
, mDiscoveredPrefixNum(0)
|
, mDiscoveredPrefixNum(0)
|
||||||
@@ -71,6 +72,8 @@ RoutingManager::RoutingManager(Instance &aInstance)
|
|||||||
, mRouterSolicitTimer(aInstance, HandleRouterSolicitTimer)
|
, mRouterSolicitTimer(aInstance, HandleRouterSolicitTimer)
|
||||||
, mRouterSolicitCount(0)
|
, mRouterSolicitCount(0)
|
||||||
{
|
{
|
||||||
|
mInfraIfLinkLocalAddress.Clear();
|
||||||
|
|
||||||
mLocalOmrPrefix.Clear();
|
mLocalOmrPrefix.Clear();
|
||||||
memset(mAdvertisedOmrPrefixes, 0, sizeof(mAdvertisedOmrPrefixes));
|
memset(mAdvertisedOmrPrefixes, 0, sizeof(mAdvertisedOmrPrefixes));
|
||||||
|
|
||||||
@@ -79,11 +82,13 @@ RoutingManager::RoutingManager(Instance &aInstance)
|
|||||||
memset(mDiscoveredPrefixes, 0, sizeof(mDiscoveredPrefixes));
|
memset(mDiscoveredPrefixes, 0, sizeof(mDiscoveredPrefixes));
|
||||||
}
|
}
|
||||||
|
|
||||||
otError RoutingManager::Init(uint32_t aInfraIfIndex)
|
otError RoutingManager::Init(uint32_t aInfraIfIndex,
|
||||||
|
bool aInfraIfIsRunning,
|
||||||
|
const Ip6::Address *aInfraIfLinkLocalAddress)
|
||||||
{
|
{
|
||||||
otError error;
|
otError error;
|
||||||
|
|
||||||
OT_ASSERT(!IsInitialized());
|
VerifyOrExit(!IsInitialized(), error = OT_ERROR_INVALID_STATE);
|
||||||
VerifyOrExit(aInfraIfIndex > 0, error = OT_ERROR_INVALID_ARGS);
|
VerifyOrExit(aInfraIfIndex > 0, error = OT_ERROR_INVALID_ARGS);
|
||||||
|
|
||||||
SuccessOrExit(error = LoadOrGenerateRandomOmrPrefix());
|
SuccessOrExit(error = LoadOrGenerateRandomOmrPrefix());
|
||||||
@@ -91,7 +96,14 @@ otError RoutingManager::Init(uint32_t aInfraIfIndex)
|
|||||||
|
|
||||||
mInfraIfIndex = aInfraIfIndex;
|
mInfraIfIndex = aInfraIfIndex;
|
||||||
|
|
||||||
|
// Initialize the infra interface status.
|
||||||
|
SuccessOrExit(error = HandleInfraIfStateChanged(mInfraIfIndex, aInfraIfIsRunning, aInfraIfLinkLocalAddress));
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
if (error != OT_ERROR_NONE)
|
||||||
|
{
|
||||||
|
mInfraIfIndex = 0;
|
||||||
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,18 +113,10 @@ otError RoutingManager::SetEnabled(bool aEnabled)
|
|||||||
|
|
||||||
VerifyOrExit(IsInitialized(), error = OT_ERROR_INVALID_STATE);
|
VerifyOrExit(IsInitialized(), error = OT_ERROR_INVALID_STATE);
|
||||||
|
|
||||||
VerifyOrExit(aEnabled != mEnabled);
|
VerifyOrExit(aEnabled != mIsEnabled);
|
||||||
|
|
||||||
mEnabled = aEnabled;
|
mIsEnabled = aEnabled;
|
||||||
|
EvaluateState();
|
||||||
if (!mEnabled)
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
else if (Get<Mle::MleRouter>().IsAttached())
|
|
||||||
{
|
|
||||||
Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
return error;
|
return error;
|
||||||
@@ -172,6 +176,18 @@ exit:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RoutingManager::EvaluateState(void)
|
||||||
|
{
|
||||||
|
if (mIsEnabled && Get<Mle::MleRouter>().IsAttached() && mInfraIfIsRunning && mInfraIfLinkLocalAddress.IsLinkLocal())
|
||||||
|
{
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RoutingManager::Start(void)
|
void RoutingManager::Start(void)
|
||||||
{
|
{
|
||||||
if (!mIsRunning)
|
if (!mIsRunning)
|
||||||
@@ -232,7 +248,7 @@ void RoutingManager::RecvIcmp6Message(uint32_t aInfraIfIndex,
|
|||||||
VerifyOrExit(IsInitialized() && mIsRunning, error = OT_ERROR_DROP);
|
VerifyOrExit(IsInitialized() && mIsRunning, error = OT_ERROR_DROP);
|
||||||
|
|
||||||
VerifyOrExit(aInfraIfIndex == mInfraIfIndex, error = OT_ERROR_DROP);
|
VerifyOrExit(aInfraIfIndex == mInfraIfIndex, error = OT_ERROR_DROP);
|
||||||
infraLinkLocalAddr = static_cast<const Ip6::Address *>(otPlatInfraIfGetLinkLocalAddress(mInfraIfIndex));
|
infraLinkLocalAddr = static_cast<const Ip6::Address *>(&mInfraIfLinkLocalAddress);
|
||||||
|
|
||||||
// Drop any ICMPv6 messages sent from myself.
|
// Drop any ICMPv6 messages sent from myself.
|
||||||
VerifyOrExit(infraLinkLocalAddr != nullptr && aSrcAddress != *infraLinkLocalAddr, error = OT_ERROR_DROP);
|
VerifyOrExit(infraLinkLocalAddr != nullptr && aSrcAddress != *infraLinkLocalAddr, error = OT_ERROR_DROP);
|
||||||
@@ -260,20 +276,42 @@ exit:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
otError RoutingManager::HandleInfraIfStateChanged(uint32_t aInfraIfIndex,
|
||||||
|
bool aIsRunning,
|
||||||
|
const Ip6::Address *aLinkLocalAddress)
|
||||||
|
{
|
||||||
|
otError error = OT_ERROR_NONE;
|
||||||
|
|
||||||
|
VerifyOrExit(IsInitialized(), error = OT_ERROR_INVALID_STATE);
|
||||||
|
VerifyOrExit(aInfraIfIndex == mInfraIfIndex, error = OT_ERROR_INVALID_ARGS);
|
||||||
|
VerifyOrExit(aLinkLocalAddress == nullptr || aLinkLocalAddress->IsLinkLocal(), error = OT_ERROR_INVALID_ARGS);
|
||||||
|
|
||||||
|
otLogInfoBr("infra interface state changed: %s, link-local-addr=%s", aIsRunning ? "RUNNING" : "NOT RUNNING",
|
||||||
|
(aLinkLocalAddress != nullptr) ? aLinkLocalAddress->ToString().AsCString() : "(null)");
|
||||||
|
|
||||||
|
mInfraIfIsRunning = aIsRunning;
|
||||||
|
if (aLinkLocalAddress == nullptr)
|
||||||
|
{
|
||||||
|
mInfraIfLinkLocalAddress.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mInfraIfLinkLocalAddress = *aLinkLocalAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
EvaluateState();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
void RoutingManager::HandleNotifierEvents(Events aEvents)
|
void RoutingManager::HandleNotifierEvents(Events aEvents)
|
||||||
{
|
{
|
||||||
VerifyOrExit(IsInitialized() && IsEnabled());
|
VerifyOrExit(IsInitialized() && IsEnabled());
|
||||||
|
|
||||||
if (aEvents.Contains(kEventThreadRoleChanged))
|
if (aEvents.Contains(kEventThreadRoleChanged))
|
||||||
{
|
{
|
||||||
if (Get<Mle::MleRouter>().IsAttached())
|
EvaluateState();
|
||||||
{
|
|
||||||
Start();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aEvents.Contains(kEventThreadNetdataChanged))
|
if (aEvents.Contains(kEventThreadNetdataChanged))
|
||||||
|
|||||||
@@ -79,12 +79,16 @@ public:
|
|||||||
* This method initializes the routing manager on given infrastructure interface.
|
* This method initializes the routing manager on given infrastructure interface.
|
||||||
*
|
*
|
||||||
* @param[in] aInfraIfIndex An infrastructure network interface index.
|
* @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.
|
||||||
*
|
*
|
||||||
* @retval OT_ERROR_NONE Successfully started the routing manager.
|
* @retval OT_ERROR_NONE Successfully started the routing manager.
|
||||||
* @retval OT_ERROR_INVALID_ARGS The index of the infra interface is not valid.
|
* @retval OT_ERROR_INVALID_ARGS The index of the infra interface is not valid.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
otError Init(uint32_t aInfraIfIndex);
|
otError Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning, const Ip6::Address *aInfraIfLinkLocalAddress);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method enables/disables the Border Routing Manager.
|
* This method enables/disables the Border Routing Manager.
|
||||||
@@ -115,6 +119,24 @@ public:
|
|||||||
const uint8_t * aBuffer,
|
const uint8_t * aBuffer,
|
||||||
uint16_t aBufferLength);
|
uint16_t aBufferLength);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
otError HandleInfraIfStateChanged(uint32_t aInfraIfIndex, bool aIsRunning, const Ip6::Address *aLinkLocalAddress);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum : uint16_t
|
enum : uint16_t
|
||||||
{
|
{
|
||||||
@@ -161,11 +183,12 @@ private:
|
|||||||
bool mIsOnLinkPrefix;
|
bool mIsOnLinkPrefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void EvaluateState(void);
|
||||||
void Start(void);
|
void Start(void);
|
||||||
void Stop(void);
|
void Stop(void);
|
||||||
void HandleNotifierEvents(Events aEvents);
|
void HandleNotifierEvents(Events aEvents);
|
||||||
bool IsInitialized(void) const { return mInfraIfIndex != 0; }
|
bool IsInitialized(void) const { return mInfraIfIndex != 0; }
|
||||||
bool IsEnabled(void) const { return mEnabled; }
|
bool IsEnabled(void) const { return mIsEnabled; }
|
||||||
otError LoadOrGenerateRandomOmrPrefix(void);
|
otError LoadOrGenerateRandomOmrPrefix(void);
|
||||||
otError LoadOrGenerateRandomOnLinkPrefix(void);
|
otError LoadOrGenerateRandomOnLinkPrefix(void);
|
||||||
|
|
||||||
@@ -210,9 +233,28 @@ private:
|
|||||||
static bool ContainsPrefix(const Ip6::Prefix &aPrefix, const Ip6::Prefix *aPrefixList, uint8_t aPrefixNum);
|
static bool ContainsPrefix(const Ip6::Prefix &aPrefix, const Ip6::Prefix *aPrefixList, uint8_t aPrefixNum);
|
||||||
static uint32_t GetPrefixExpireDelay(uint32_t aValidLifetime);
|
static uint32_t GetPrefixExpireDelay(uint32_t aValidLifetime);
|
||||||
|
|
||||||
bool mIsRunning;
|
// Indicates whether the Routing Manager is running (started).
|
||||||
|
bool mIsRunning;
|
||||||
|
|
||||||
|
// Indicates whether the Routing manager is enabled.
|
||||||
|
// The Routing Manager will be stopped if we are
|
||||||
|
// disabled.
|
||||||
|
bool mIsEnabled;
|
||||||
|
|
||||||
|
// Indicates whether the infra interface is running.
|
||||||
|
// The Routing Manager will be stopped when the
|
||||||
|
// Infra interface is not running.
|
||||||
|
bool mInfraIfIsRunning;
|
||||||
|
|
||||||
|
// The index of the infra interface on which Router
|
||||||
|
// Advertisement messages will be sent.
|
||||||
uint32_t mInfraIfIndex;
|
uint32_t mInfraIfIndex;
|
||||||
bool mEnabled;
|
|
||||||
|
// 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
|
// The OMR prefix loaded from local persistent storage or randomly generated
|
||||||
// if non is found in persistent storage.
|
// if non is found in persistent storage.
|
||||||
|
|||||||
+164
-44
@@ -45,24 +45,30 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/icmp6.h>
|
#include <netinet/icmp6.h>
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <openthread/border_router.h>
|
||||||
#include <openthread/platform/infra_if.h>
|
#include <openthread/platform/infra_if.h>
|
||||||
|
|
||||||
#include "common/code_utils.hpp"
|
#include "common/code_utils.hpp"
|
||||||
|
#include "common/debug.hpp"
|
||||||
#include "lib/platform/exit_code.h"
|
#include "lib/platform/exit_code.h"
|
||||||
|
|
||||||
static char sInfraIfName[IFNAMSIZ];
|
static char sInfraIfName[IFNAMSIZ];
|
||||||
static uint32_t sInfraIfIndex = 0;
|
static uint32_t sInfraIfIndex = 0;
|
||||||
static int sInfraIfIcmp6Socket = -1;
|
static int sInfraIfIcmp6Socket = -1;
|
||||||
|
static int sNetLinkSocket = -1;
|
||||||
static otIp6Address sInfraIfLinkLocalAddr;
|
static otIp6Address sInfraIfLinkLocalAddr;
|
||||||
|
|
||||||
const otIp6Address *otPlatInfraIfGetLinkLocalAddress(uint32_t aInfraIfIndex)
|
static int CreateIcmp6Socket(void);
|
||||||
{
|
static int CreateNetLinkSocket(void);
|
||||||
VerifyOrDie(aInfraIfIndex == sInfraIfIndex, OT_EXIT_FAILURE);
|
static void ReceiveNetLinkMessage(otInstance *aInstance);
|
||||||
return &sInfraIfLinkLocalAddr;
|
static void ReceiveIcmp6Message(otInstance *aInstance);
|
||||||
}
|
|
||||||
|
|
||||||
otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,
|
otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,
|
||||||
const otIp6Address *aDestAddress,
|
const otIp6Address *aDestAddress,
|
||||||
@@ -138,10 +144,10 @@ exit:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static otError InitLinkLocalAddress(void)
|
const otIp6Address *platformInfraIfGetLinkLocalAddress(void)
|
||||||
{
|
{
|
||||||
otError error;
|
const otIp6Address *ret = nullptr;
|
||||||
struct ifaddrs *ifAddrs = nullptr;
|
struct ifaddrs * ifAddrs = nullptr;
|
||||||
|
|
||||||
VerifyOrDie(getifaddrs(&ifAddrs) != -1, OT_EXIT_ERROR_ERRNO);
|
VerifyOrDie(getifaddrs(&ifAddrs) != -1, OT_EXIT_ERROR_ERRNO);
|
||||||
|
|
||||||
@@ -158,51 +164,50 @@ static otError InitLinkLocalAddress(void)
|
|||||||
if (IN6_IS_ADDR_LINKLOCAL(&ip6Addr->sin6_addr))
|
if (IN6_IS_ADDR_LINKLOCAL(&ip6Addr->sin6_addr))
|
||||||
{
|
{
|
||||||
memcpy(&sInfraIfLinkLocalAddr, &ip6Addr->sin6_addr, sizeof(sInfraIfLinkLocalAddr));
|
memcpy(&sInfraIfLinkLocalAddr, &ip6Addr->sin6_addr, sizeof(sInfraIfLinkLocalAddr));
|
||||||
ExitNow(error = OT_ERROR_NONE);
|
ExitNow(ret = &sInfraIfLinkLocalAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
otLogCritPlat("cannot find IPv6 link-local address for interface %s", sInfraIfName);
|
otLogWarnPlat("cannot find IPv6 link-local address for interface %s", sInfraIfName);
|
||||||
error = OT_ERROR_NOT_FOUND;
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
freeifaddrs(ifAddrs);
|
freeifaddrs(ifAddrs);
|
||||||
return error;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void platformInfraIfInit(otInstance *aInstance, const char *aIfName)
|
bool platformInfraIfIsRunning(void)
|
||||||
{
|
{
|
||||||
OT_UNUSED_VARIABLE(aInstance);
|
int sock;
|
||||||
|
struct ifreq ifReq;
|
||||||
|
|
||||||
|
OT_ASSERT(sInfraIfIndex != 0);
|
||||||
|
|
||||||
|
sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
|
||||||
|
VerifyOrDie(sock != -1, OT_EXIT_ERROR_ERRNO);
|
||||||
|
|
||||||
|
memset(&ifReq, 0, sizeof(ifReq));
|
||||||
|
strncpy(ifReq.ifr_name, sInfraIfName, sizeof(ifReq.ifr_name));
|
||||||
|
VerifyOrDie(ioctl(sock, SIOCGIFFLAGS, &ifReq) != -1, OT_EXIT_ERROR_ERRNO);
|
||||||
|
|
||||||
|
close(sock);
|
||||||
|
|
||||||
|
return (ifReq.ifr_flags & IFF_RUNNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CreateIcmp6Socket(void)
|
||||||
|
{
|
||||||
int sock;
|
int sock;
|
||||||
|
int rval;
|
||||||
struct icmp6_filter filter;
|
struct icmp6_filter filter;
|
||||||
ssize_t rval;
|
|
||||||
const int kEnable = 1;
|
const int kEnable = 1;
|
||||||
const int kIpv6ChecksumOffset = 2;
|
const int kIpv6ChecksumOffset = 2;
|
||||||
const int kHopLimit = 255;
|
const int kHopLimit = 255;
|
||||||
uint32_t ifIndex = 0;
|
|
||||||
|
|
||||||
if (strlen(aIfName) >= sizeof(sInfraIfName))
|
|
||||||
{
|
|
||||||
otLogCritPlat("infra interface name '%s' is too long", aIfName);
|
|
||||||
DieNow(OT_EXIT_INVALID_ARGUMENTS);
|
|
||||||
}
|
|
||||||
strcpy(sInfraIfName, aIfName);
|
|
||||||
|
|
||||||
// Initializes the infra interface.
|
|
||||||
ifIndex = if_nametoindex(aIfName);
|
|
||||||
if (ifIndex == 0)
|
|
||||||
{
|
|
||||||
otLogCritPlat("failed to get the index for infra interface %s: %s", aIfName, strerror(errno));
|
|
||||||
DieNow(OT_EXIT_ERROR_ERRNO);
|
|
||||||
}
|
|
||||||
sInfraIfIndex = ifIndex;
|
|
||||||
|
|
||||||
// Initializes the ICMPv6 socket.
|
// Initializes the ICMPv6 socket.
|
||||||
sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||||
VerifyOrDie(sock != -1, OT_EXIT_ERROR_ERRNO);
|
VerifyOrDie(sock != -1, OT_EXIT_ERROR_ERRNO);
|
||||||
|
|
||||||
// Only accept router advertisements and router solicits.
|
// Only accept router advertisements and solicitations.
|
||||||
ICMP6_FILTER_SETBLOCKALL(&filter);
|
ICMP6_FILTER_SETBLOCKALL(&filter);
|
||||||
ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
|
ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
|
||||||
ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
|
ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
|
||||||
@@ -231,15 +236,43 @@ void platformInfraIfInit(otInstance *aInstance, const char *aIfName)
|
|||||||
rval = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kHopLimit, sizeof(kHopLimit));
|
rval = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kHopLimit, sizeof(kHopLimit));
|
||||||
VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
|
VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t platformInfraIfInit(otInstance *aInstance, const char *aIfName)
|
||||||
|
{
|
||||||
|
OT_UNUSED_VARIABLE(aInstance);
|
||||||
|
|
||||||
|
ssize_t rval;
|
||||||
|
uint32_t ifIndex = 0;
|
||||||
|
|
||||||
|
if (strlen(aIfName) >= sizeof(sInfraIfName))
|
||||||
|
{
|
||||||
|
otLogCritPlat("infra interface name '%s' is too long", aIfName);
|
||||||
|
DieNow(OT_EXIT_INVALID_ARGUMENTS);
|
||||||
|
}
|
||||||
|
strcpy(sInfraIfName, aIfName);
|
||||||
|
|
||||||
|
// Initializes the infra interface.
|
||||||
|
ifIndex = if_nametoindex(aIfName);
|
||||||
|
if (ifIndex == 0)
|
||||||
|
{
|
||||||
|
otLogCritPlat("failed to get the index for infra interface %s", aIfName);
|
||||||
|
DieNow(OT_EXIT_INVALID_ARGUMENTS);
|
||||||
|
}
|
||||||
|
sInfraIfIndex = ifIndex;
|
||||||
|
|
||||||
|
sInfraIfIcmp6Socket = CreateIcmp6Socket();
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
rval = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, sInfraIfName, strlen(sInfraIfName));
|
rval = setsockopt(sInfraIfIcmp6Socket, SOL_SOCKET, SO_BINDTODEVICE, sInfraIfName, strlen(sInfraIfName));
|
||||||
#else // __NetBSD__ || __FreeBSD__ || __APPLE__
|
#else // __NetBSD__ || __FreeBSD__ || __APPLE__
|
||||||
rval = setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &sInfraIfIndex, sizeof(sInfraIfIndex));
|
rval = setsockopt(sInfraIfIcmp6Socket, IPPROTO_IP, IP_BOUND_IF, &sInfraIfIndex, sizeof(sInfraIfIndex));
|
||||||
#endif // __linux__
|
#endif // __linux__
|
||||||
VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
|
VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
|
||||||
|
|
||||||
sInfraIfIcmp6Socket = sock;
|
sNetLinkSocket = CreateNetLinkSocket();
|
||||||
SuccessOrDie(InitLinkLocalAddress());
|
|
||||||
|
return sInfraIfIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void platformInfraIfDeinit(void)
|
void platformInfraIfDeinit(void)
|
||||||
@@ -250,21 +283,97 @@ void platformInfraIfDeinit(void)
|
|||||||
sInfraIfIcmp6Socket = -1;
|
sInfraIfIcmp6Socket = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sNetLinkSocket != -1)
|
||||||
|
{
|
||||||
|
close(sNetLinkSocket);
|
||||||
|
sNetLinkSocket = -1;
|
||||||
|
}
|
||||||
|
|
||||||
sInfraIfIndex = 0;
|
sInfraIfIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void platformInfraIfUpdateFdSet(fd_set &aReadFdSet, int &aMaxFd)
|
void platformInfraIfUpdateFdSet(fd_set &aReadFdSet, int &aMaxFd)
|
||||||
{
|
{
|
||||||
VerifyOrExit(sInfraIfIcmp6Socket != -1);
|
VerifyOrExit(sInfraIfIcmp6Socket != -1);
|
||||||
|
VerifyOrExit(sNetLinkSocket != -1);
|
||||||
|
|
||||||
FD_SET(sInfraIfIcmp6Socket, &aReadFdSet);
|
FD_SET(sInfraIfIcmp6Socket, &aReadFdSet);
|
||||||
aMaxFd = OT_MAX(aMaxFd, sInfraIfIcmp6Socket);
|
aMaxFd = OT_MAX(aMaxFd, sInfraIfIcmp6Socket);
|
||||||
|
|
||||||
|
FD_SET(sNetLinkSocket, &aReadFdSet);
|
||||||
|
aMaxFd = OT_MAX(aMaxFd, sNetLinkSocket);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void platformInfraIfProcess(otInstance *aInstance, const fd_set &aReadFdSet)
|
// Create a net-link socket that subscribes to link & addresses events.
|
||||||
|
static int CreateNetLinkSocket(void)
|
||||||
|
{
|
||||||
|
int sock;
|
||||||
|
int rval;
|
||||||
|
struct sockaddr_nl addr;
|
||||||
|
|
||||||
|
sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
||||||
|
VerifyOrDie(sock != -1, OT_EXIT_ERROR_ERRNO);
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.nl_family = AF_NETLINK;
|
||||||
|
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR;
|
||||||
|
addr.nl_pid = getpid();
|
||||||
|
|
||||||
|
rval = bind(sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr));
|
||||||
|
VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReceiveNetLinkMessage(otInstance *aInstance)
|
||||||
|
{
|
||||||
|
const size_t kMaxNetLinkBufSize = 8192;
|
||||||
|
ssize_t len;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
nlmsghdr mHeader;
|
||||||
|
uint8_t mBuffer[kMaxNetLinkBufSize];
|
||||||
|
} msgBuffer;
|
||||||
|
|
||||||
|
len = recv(sNetLinkSocket, msgBuffer.mBuffer, sizeof(msgBuffer.mBuffer), 0);
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
otLogCritPlat("failed to receive netlink message: %s", strerror(errno));
|
||||||
|
ExitNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (struct nlmsghdr *header = &msgBuffer.mHeader; NLMSG_OK(header, static_cast<size_t>(len));
|
||||||
|
header = NLMSG_NEXT(header, len))
|
||||||
|
{
|
||||||
|
switch (header->nlmsg_type)
|
||||||
|
{
|
||||||
|
case RTM_NEWLINK:
|
||||||
|
case RTM_DELLINK:
|
||||||
|
case RTM_NEWADDR:
|
||||||
|
case RTM_DELADDR:
|
||||||
|
SuccessOrDie(otPlatInfraIfStateChanged(aInstance, sInfraIfIndex, platformInfraIfIsRunning(),
|
||||||
|
platformInfraIfGetLinkLocalAddress()));
|
||||||
|
break;
|
||||||
|
case NLMSG_ERROR:
|
||||||
|
{
|
||||||
|
struct nlmsgerr *errMsg = reinterpret_cast<struct nlmsgerr *>(NLMSG_DATA(header));
|
||||||
|
|
||||||
|
OT_UNUSED_VARIABLE(errMsg);
|
||||||
|
otLogWarnPlat("netlink NLMSG_ERROR response: seq=%u, error=%d", header->nlmsg_seq, errMsg->error);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReceiveIcmp6Message(otInstance *aInstance)
|
||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
otError error = OT_ERROR_NONE;
|
||||||
uint8_t buffer[1500];
|
uint8_t buffer[1500];
|
||||||
@@ -281,10 +390,6 @@ void platformInfraIfProcess(otInstance *aInstance, const fd_set &aReadFdSet)
|
|||||||
struct sockaddr_in6 srcAddr;
|
struct sockaddr_in6 srcAddr;
|
||||||
struct in6_addr dstAddr;
|
struct in6_addr dstAddr;
|
||||||
|
|
||||||
// It is not an error when there is no input data on the socket.
|
|
||||||
VerifyOrExit(sInfraIfIcmp6Socket != -1);
|
|
||||||
VerifyOrExit(FD_ISSET(sInfraIfIcmp6Socket, &aReadFdSet));
|
|
||||||
|
|
||||||
memset(&srcAddr, 0, sizeof(srcAddr));
|
memset(&srcAddr, 0, sizeof(srcAddr));
|
||||||
memset(&dstAddr, 0, sizeof(dstAddr));
|
memset(&dstAddr, 0, sizeof(dstAddr));
|
||||||
|
|
||||||
@@ -340,8 +445,23 @@ exit:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t platformInfraIfGetIndex(void)
|
void platformInfraIfProcess(otInstance *aInstance, const fd_set &aReadFdSet)
|
||||||
{
|
{
|
||||||
return sInfraIfIndex;
|
VerifyOrExit(sInfraIfIcmp6Socket != -1);
|
||||||
|
VerifyOrExit(sNetLinkSocket != -1);
|
||||||
|
|
||||||
|
if (FD_ISSET(sInfraIfIcmp6Socket, &aReadFdSet))
|
||||||
|
{
|
||||||
|
ReceiveIcmp6Message(aInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(sNetLinkSocket, &aReadFdSet))
|
||||||
|
{
|
||||||
|
ReceiveNetLinkMessage(aInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
|
|
||||||
#include <openthread/error.h>
|
#include <openthread/error.h>
|
||||||
#include <openthread/instance.h>
|
#include <openthread/instance.h>
|
||||||
|
#include <openthread/ip6.h>
|
||||||
#include <openthread/openthread-system.h>
|
#include <openthread/openthread-system.h>
|
||||||
#include <openthread/platform/time.h>
|
#include <openthread/platform/time.h>
|
||||||
|
|
||||||
@@ -505,8 +506,10 @@ extern unsigned int gBackboneNetifIndex;
|
|||||||
* @param[in] aInstance The OpenThread instance.
|
* @param[in] aInstance The OpenThread instance.
|
||||||
* @param[in] aIfName The name of the infrastructure interface.
|
* @param[in] aIfName The name of the infrastructure interface.
|
||||||
*
|
*
|
||||||
|
* @returns The index of the infrastructure interface.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void platformInfraIfInit(otInstance *aInstance, const char *aIfName);
|
uint32_t platformInfraIfInit(otInstance *aInstance, const char *aIfName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function deinitializes the infrastructure interface.
|
* This function deinitializes the infrastructure interface.
|
||||||
@@ -514,6 +517,22 @@ void platformInfraIfInit(otInstance *aInstance, const char *aIfName);
|
|||||||
*/
|
*/
|
||||||
void platformInfraIfDeinit(void);
|
void platformInfraIfDeinit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function tells if the infrastructure interface is running.
|
||||||
|
*
|
||||||
|
* @returns TRUE if the infrastructure interface is running, FALSE if not.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
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.
|
* This function updates the read fd set.
|
||||||
*
|
*
|
||||||
@@ -532,14 +551,6 @@ void platformInfraIfUpdateFdSet(fd_set &aReadFdSet, int &aMaxFd);
|
|||||||
*/
|
*/
|
||||||
void platformInfraIfProcess(otInstance *aInstance, const fd_set &aReadFdSet);
|
void platformInfraIfProcess(otInstance *aInstance, const fd_set &aReadFdSet);
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns the index of the infrastructure interface.
|
|
||||||
*
|
|
||||||
* @returns The index of the infrastructure interface. 0 indicates invalid index.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
uint32_t platformInfraIfGetIndex(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#include <openthread/heap.h>
|
#include <openthread/heap.h>
|
||||||
#include <openthread/tasklet.h>
|
#include <openthread/tasklet.h>
|
||||||
#include <openthread/platform/alarm-milli.h>
|
#include <openthread/platform/alarm-milli.h>
|
||||||
|
#include <openthread/platform/infra_if.h>
|
||||||
#include <openthread/platform/otns.h>
|
#include <openthread/platform/otns.h>
|
||||||
#include <openthread/platform/radio.h>
|
#include <openthread/platform/radio.h>
|
||||||
#include <openthread/platform/uart.h>
|
#include <openthread/platform/uart.h>
|
||||||
@@ -100,8 +101,21 @@ otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||||
// Reuse the backbone interface name.
|
{
|
||||||
platformInfraIfInit(instance, aPlatformConfig->mBackboneInterfaceName);
|
uint32_t infraIfIndex;
|
||||||
|
|
||||||
|
// Reuse the backbone interface name.
|
||||||
|
if (aPlatformConfig->mBackboneInterfaceName == nullptr || strlen(aPlatformConfig->mBackboneInterfaceName) == 0)
|
||||||
|
{
|
||||||
|
DieNowWithMessage("no infra interface is specified", OT_EXIT_INVALID_ARGUMENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
infraIfIndex = platformInfraIfInit(instance, aPlatformConfig->mBackboneInterfaceName);
|
||||||
|
|
||||||
|
SuccessOrDie(otBorderRoutingInit(instance, infraIfIndex, platformInfraIfIsRunning(),
|
||||||
|
platformInfraIfGetLinkLocalAddress()));
|
||||||
|
SuccessOrDie(otBorderRoutingSetEnabled(instance, /* aEnabled */ true));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
|
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
|
||||||
@@ -114,10 +128,6 @@ otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
|
|||||||
SuccessOrDie(otSetStateChangedCallback(instance, processStateChange, instance));
|
SuccessOrDie(otSetStateChangedCallback(instance, processStateChange, instance));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
|
||||||
SuccessOrDie(otBorderRoutingInit(instance, platformInfraIfGetIndex()));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -255,6 +255,60 @@ class SingleBorderRouter(thread_cert.TestCase):
|
|||||||
self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
|
self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
|
||||||
backbone=True))
|
backbone=True))
|
||||||
|
|
||||||
|
#
|
||||||
|
# Case 4. The Routing Manager should be stopped if the infra interface went down.
|
||||||
|
#
|
||||||
|
|
||||||
|
self.nodes[BR1].disable_ether()
|
||||||
|
|
||||||
|
self.simulator.go(10)
|
||||||
|
self.collect_ipaddrs()
|
||||||
|
|
||||||
|
logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
|
||||||
|
logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
|
||||||
|
logging.info("HOST addrs: %r", self.nodes[HOST].get_addrs())
|
||||||
|
|
||||||
|
self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 0)
|
||||||
|
self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 0)
|
||||||
|
self.assertTrue(len(self.nodes[BR1].get_routes()) == 0)
|
||||||
|
self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 0)
|
||||||
|
self.assertTrue(len(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 0)
|
||||||
|
self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 0)
|
||||||
|
|
||||||
|
self.nodes[BR1].enable_ether()
|
||||||
|
|
||||||
|
# It takes around 10 seconds to start sending RA messages.
|
||||||
|
self.simulator.go(15)
|
||||||
|
self.collect_ipaddrs()
|
||||||
|
|
||||||
|
logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
|
||||||
|
logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
|
||||||
|
logging.info("HOST addrs: %r", self.nodes[HOST].get_addrs())
|
||||||
|
|
||||||
|
self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 1)
|
||||||
|
self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 1)
|
||||||
|
self.assertTrue(len(self.nodes[BR1].get_routes()) == 1)
|
||||||
|
self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 1)
|
||||||
|
|
||||||
|
# The same local OMR and on-link prefix should be re-registered.
|
||||||
|
self.assertEqual(omr_prefix, self.nodes[BR1].get_prefixes()[0])
|
||||||
|
self.assertEqual(omr_prefix, self.nodes[ROUTER1].get_prefixes()[0])
|
||||||
|
self.assertEqual(external_route, self.nodes[BR1].get_routes()[0])
|
||||||
|
self.assertEqual(external_route, self.nodes[ROUTER1].get_routes()[0])
|
||||||
|
|
||||||
|
self.assertTrue(len(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
|
||||||
|
self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
|
||||||
|
self.assertTrue(len(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)) == 1)
|
||||||
|
|
||||||
|
self.assertEqual(br1_omr_address, self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0])
|
||||||
|
self.assertEqual(router1_omr_address, self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0])
|
||||||
|
self.assertEqual(host_ula_address, self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0])
|
||||||
|
|
||||||
|
# Router1 can ping to/from the Host on infra link.
|
||||||
|
self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
|
||||||
|
self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
|
||||||
|
backbone=True))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -2592,6 +2592,18 @@ class LinuxHost():
|
|||||||
PING_RESPONSE_PATTERN = re.compile(r'\d+ bytes from .*:.*')
|
PING_RESPONSE_PATTERN = re.compile(r'\d+ bytes from .*:.*')
|
||||||
ETH_DEV = config.BACKBONE_IFNAME
|
ETH_DEV = config.BACKBONE_IFNAME
|
||||||
|
|
||||||
|
def enable_ether(self):
|
||||||
|
"""Enable the ethernet interface.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.bash(f'ifconfig {self.ETH_DEV} up')
|
||||||
|
|
||||||
|
def disable_ether(self):
|
||||||
|
"""Disable the ethernet interface.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.bash(f'ifconfig {self.ETH_DEV} down')
|
||||||
|
|
||||||
def get_ether_addrs(self):
|
def get_ether_addrs(self):
|
||||||
output = self.bash(f'ip -6 addr list dev {self.ETH_DEV}')
|
output = self.bash(f'ip -6 addr list dev {self.ETH_DEV}')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user