mirror of
https://github.com/espressif/openthread.git
synced 2026-08-11 05:07:47 +00:00
[tmf] add Backbone TMF agent (#5471)
This commit is contained in:
@@ -176,6 +176,7 @@ LOCAL_SRC_FILES := \
|
||||
src/core/api/thread_api.cpp \
|
||||
src/core/api/thread_ftd_api.cpp \
|
||||
src/core/api/udp_api.cpp \
|
||||
src/core/backbone_router/backbone_tmf.cpp \
|
||||
src/core/backbone_router/bbr_leader.cpp \
|
||||
src/core/backbone_router/bbr_local.cpp \
|
||||
src/core/backbone_router/bbr_manager.cpp \
|
||||
@@ -291,6 +292,7 @@ LOCAL_SRC_FILES := \
|
||||
src/lib/spinel/spinel_encoder.cpp \
|
||||
src/lib/url/url.cpp \
|
||||
src/posix/platform/alarm.cpp \
|
||||
src/posix/platform/backbone.cpp \
|
||||
src/posix/platform/entropy.cpp \
|
||||
src/posix/platform/hdlc_interface.cpp \
|
||||
src/posix/platform/logging.cpp \
|
||||
|
||||
@@ -39,10 +39,15 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This enumeration defines the OpenThread network interface identifiers.
|
||||
*
|
||||
*/
|
||||
typedef enum otNetifIdentifier
|
||||
{
|
||||
OT_NETIF_UNSPECIFIED = 0, ///< Unspecified network interface.
|
||||
OT_NETIF_THREAD, ///< The Thread interface.
|
||||
OT_NETIF_BACKBONE, ///< The Backbone interface.
|
||||
} otNetifIdentifier;
|
||||
|
||||
/**
|
||||
|
||||
@@ -319,6 +319,8 @@ openthread_core_files = [
|
||||
"api/thread_api.cpp",
|
||||
"api/thread_ftd_api.cpp",
|
||||
"api/udp_api.cpp",
|
||||
"backbone_router/backbone_tmf.cpp",
|
||||
"backbone_router/backbone_tmf.hpp",
|
||||
"backbone_router/bbr_leader.cpp",
|
||||
"backbone_router/bbr_leader.hpp",
|
||||
"backbone_router/bbr_local.cpp",
|
||||
|
||||
@@ -102,6 +102,7 @@ set(COMMON_SOURCES
|
||||
api/thread_api.cpp
|
||||
api/thread_ftd_api.cpp
|
||||
api/udp_api.cpp
|
||||
backbone_router/backbone_tmf.cpp
|
||||
backbone_router/bbr_leader.cpp
|
||||
backbone_router/bbr_local.cpp
|
||||
backbone_router/bbr_manager.cpp
|
||||
|
||||
@@ -144,6 +144,7 @@ SOURCES_COMMON = \
|
||||
api/thread_api.cpp \
|
||||
api/thread_ftd_api.cpp \
|
||||
api/udp_api.cpp \
|
||||
backbone_router/backbone_tmf.cpp \
|
||||
backbone_router/bbr_leader.cpp \
|
||||
backbone_router/bbr_local.cpp \
|
||||
backbone_router/bbr_manager.cpp \
|
||||
@@ -325,6 +326,7 @@ endif # OPENTHREAD_ENABLE_VENDOR_EXTENSION
|
||||
|
||||
HEADERS_COMMON = \
|
||||
openthread-core-config.h \
|
||||
backbone_router/backbone_tmf.hpp \
|
||||
backbone_router/bbr_leader.hpp \
|
||||
backbone_router/bbr_local.hpp \
|
||||
backbone_router/bbr_manager.hpp \
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2020, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements Backbone Thread Management Framework (TMF) functionalities.
|
||||
*/
|
||||
|
||||
#include "backbone_tmf.hpp"
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
|
||||
#include "common/locator-getters.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace BackboneRouter {
|
||||
|
||||
otError BackboneTmfAgent::Start(void)
|
||||
{
|
||||
return Coap::Start(kBackboneUdpPort, OT_NETIF_BACKBONE);
|
||||
}
|
||||
|
||||
otError BackboneTmfAgent::Filter(const ot::Coap::Message &aMessage,
|
||||
const Ip6::MessageInfo & aMessageInfo,
|
||||
void * aContext)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aMessage);
|
||||
|
||||
return static_cast<BackboneTmfAgent *>(aContext)->IsBackboneTmfMessage(aMessageInfo) ? OT_ERROR_NONE
|
||||
: OT_ERROR_NOT_TMF;
|
||||
}
|
||||
|
||||
bool BackboneTmfAgent::IsBackboneTmfMessage(const Ip6::MessageInfo &aMessageInfo) const
|
||||
{
|
||||
const Ip6::Address &dst = aMessageInfo.GetSockAddr();
|
||||
const Ip6::Address &src = aMessageInfo.GetPeerAddr();
|
||||
|
||||
// A Backbone TMF message must comply with following rules:
|
||||
// The destination must be one of:
|
||||
// 1. All Network BBRs (Link-Local scope)
|
||||
// 2. All Domain BBRs (Link-Local scope)
|
||||
// 3. A Backbone Link-Local address
|
||||
// The source must be a Backbone Link-local address.
|
||||
return (Get<BackboneRouter::Local>().IsEnabled() && src.IsLinkLocal() &&
|
||||
(dst.IsLinkLocal() || dst == Get<BackboneRouter::Local>().GetAllNetworkBackboneRoutersAddress() ||
|
||||
dst == Get<BackboneRouter::Local>().GetAllDomainBackboneRoutersAddress()));
|
||||
}
|
||||
|
||||
} // namespace BackboneRouter
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2020, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for Backbone TMF functionality.
|
||||
*/
|
||||
|
||||
#ifndef OT_CORE_THREAD_BACKBONE_TMF_HPP_
|
||||
#define OT_CORE_THREAD_BACKBONE_TMF_HPP_
|
||||
|
||||
#include "coap/coap.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace BackboneRouter {
|
||||
|
||||
enum
|
||||
{
|
||||
kBackboneUdpPort = 61631, ///< Backbone TMF UDP Port
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements functionality of the Backbone TMF agent.
|
||||
*
|
||||
*/
|
||||
class BackboneTmfAgent : public Coap::Coap
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
* @param[in] aInstance A reference to the OpenThread instance.
|
||||
*
|
||||
*/
|
||||
explicit BackboneTmfAgent(Instance &aInstance)
|
||||
: Coap::Coap(aInstance)
|
||||
{
|
||||
SetInterceptor(&Filter, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method starts the TMF agent.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started the CoAP service.
|
||||
* @retval OT_ERROR_ALREADY Already started.
|
||||
*
|
||||
*/
|
||||
otError Start(void);
|
||||
|
||||
/**
|
||||
* This method returns whether @p aMessageInfo meets Backbone Thread Management Framework Addressing Rules.
|
||||
*
|
||||
* @retval true Thread Management Framework Addressing Rules are met.
|
||||
* @retval false Thread Management Framework Addressing Rules are not met.
|
||||
*
|
||||
*/
|
||||
bool IsBackboneTmfMessage(const Ip6::MessageInfo &aMessageInfo) const;
|
||||
|
||||
private:
|
||||
static otError Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
|
||||
};
|
||||
|
||||
} // namespace BackboneRouter
|
||||
} // namespace ot
|
||||
|
||||
#endif // OT_CORE_THREAD_BACKBONE_TMF_HPP_
|
||||
@@ -56,6 +56,7 @@ Manager::Manager(Instance &aInstance)
|
||||
, mNdProxyTable(aInstance)
|
||||
, mMulticastListenersTable(aInstance)
|
||||
, mTimer(aInstance, Manager::HandleTimer, this)
|
||||
, mBackboneTmfAgent(aInstance)
|
||||
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
||||
, mDuaResponseStatus(ThreadStatusTlv::kDuaSuccess)
|
||||
, mMlrResponseStatus(ThreadStatusTlv::kMlrSuccess)
|
||||
@@ -67,6 +68,8 @@ Manager::Manager(Instance &aInstance)
|
||||
|
||||
void Manager::HandleNotifierEvents(Events aEvents)
|
||||
{
|
||||
otError error;
|
||||
|
||||
if (aEvents.Contains(kEventThreadBackboneRouterStateChanged))
|
||||
{
|
||||
if (Get<BackboneRouter::Local>().GetState() == OT_BACKBONE_ROUTER_STATE_DISABLED)
|
||||
@@ -75,6 +78,17 @@ void Manager::HandleNotifierEvents(Events aEvents)
|
||||
Get<Tmf::TmfAgent>().RemoveResource(mDuaRegistration);
|
||||
mTimer.Stop();
|
||||
mMulticastListenersTable.Clear();
|
||||
|
||||
error = mBackboneTmfAgent.Stop();
|
||||
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
otLogWarnBbr("Stop Backbone TMF agent: %s", otThreadErrorToString(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
otLogInfoBbr("Stop Backbone TMF agent: %s", otThreadErrorToString(error));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -84,6 +98,17 @@ void Manager::HandleNotifierEvents(Events aEvents)
|
||||
{
|
||||
mTimer.Start(kTimerInterval);
|
||||
}
|
||||
|
||||
error = mBackboneTmfAgent.Start();
|
||||
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
otLogCritBbr("Start Backbone TMF agent: %s", otThreadErrorToString(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
otLogInfoBbr("Start Backbone TMF agent: %s", otThreadErrorToString(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <openthread/backbone_router.h>
|
||||
#include <openthread/backbone_router_ftd.h>
|
||||
|
||||
#include "backbone_router/backbone_tmf.hpp"
|
||||
#include "backbone_router/bbr_leader.hpp"
|
||||
#include "backbone_router/multicast_listeners_table.hpp"
|
||||
#include "backbone_router/ndproxy_table.hpp"
|
||||
@@ -123,6 +124,14 @@ public:
|
||||
*/
|
||||
bool ShouldForwardDuaToBackbone(const Ip6::Address &aAddress);
|
||||
|
||||
/**
|
||||
* This method returns a reference to the Backbone TMF agent.
|
||||
*
|
||||
* @returns A reference to the Backbone TMF agent.
|
||||
*
|
||||
*/
|
||||
BackboneTmfAgent &GetBackboneTmfAgent(void) { return mBackboneTmfAgent; }
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
@@ -166,6 +175,8 @@ private:
|
||||
MulticastListenersTable mMulticastListenersTable;
|
||||
TimerMilli mTimer;
|
||||
|
||||
BackboneTmfAgent mBackboneTmfAgent;
|
||||
|
||||
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
||||
Ip6::InterfaceIdentifier mDuaResponseTargetMlIid;
|
||||
ThreadStatusTlv::DuaStatus mDuaResponseStatus;
|
||||
|
||||
+13
-2
@@ -1018,14 +1018,25 @@ Coap::Coap(Instance &aInstance)
|
||||
{
|
||||
}
|
||||
|
||||
otError Coap::Start(uint16_t aPort)
|
||||
otError Coap::Start(uint16_t aPort, otNetifIdentifier aNetifIdentifier)
|
||||
{
|
||||
otError error;
|
||||
bool socketOpened = false;
|
||||
|
||||
VerifyOrExit(!mSocket.IsBound(), error = OT_ERROR_ALREADY);
|
||||
|
||||
SuccessOrExit(error = mSocket.Open(&Coap::HandleUdpReceive, this));
|
||||
VerifyOrExit((error = mSocket.Bind(aPort)) == OT_ERROR_NONE, IgnoreError(mSocket.Close()));
|
||||
socketOpened = true;
|
||||
|
||||
SuccessOrExit(error = mSocket.BindToNetif(aNetifIdentifier));
|
||||
SuccessOrExit(error = mSocket.Bind(aPort));
|
||||
|
||||
exit:
|
||||
if (error != OT_ERROR_NONE && socketOpened)
|
||||
{
|
||||
IgnoreError(mSocket.Close());
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@@ -606,13 +606,14 @@ public:
|
||||
/**
|
||||
* This method starts the CoAP service.
|
||||
*
|
||||
* @param[in] aPort The local UDP port to bind to.
|
||||
* @param[in] aPort The local UDP port to bind to.
|
||||
* @param[in] aNetifIdentifier The network interface identifier to bind.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started the CoAP service.
|
||||
* @retval OT_ERROR_ALREADY Already started.
|
||||
*
|
||||
*/
|
||||
otError Start(uint16_t aPort);
|
||||
otError Start(uint16_t aPort, otNetifIdentifier aNetifIdentifier = OT_NETIF_UNSPECIFIED);
|
||||
|
||||
/**
|
||||
* This method stops the CoAP service.
|
||||
|
||||
@@ -763,10 +763,16 @@ template <> inline BackboneRouter::MulticastListenersTable &Instance::Get(void)
|
||||
{
|
||||
return mThreadNetif.mBackboneRouterManager.GetMulticastListenersTable();
|
||||
}
|
||||
|
||||
template <> inline BackboneRouter::NdProxyTable &Instance::Get(void)
|
||||
{
|
||||
return mThreadNetif.mBackboneRouterManager.GetNdProxyTable();
|
||||
}
|
||||
|
||||
template <> inline BackboneRouter::BackboneTmfAgent &Instance::Get(void)
|
||||
{
|
||||
return mThreadNetif.mBackboneRouterManager.GetBackboneTmfAgent();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLR_ENABLE || OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
|
||||
|
||||
@@ -392,6 +392,73 @@ public:
|
||||
return const_cast<const LinkedList *>(this)->Find(aEntry, const_cast<const Type *&>(aPrevEntry));
|
||||
}
|
||||
|
||||
/**
|
||||
* This template method searches within a given range of the linked list to find an entry matching a given
|
||||
* indicator.
|
||||
*
|
||||
* The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries
|
||||
* in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each
|
||||
* `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly:
|
||||
*
|
||||
* bool Type::Matches(const Indicator &aIndicator) const
|
||||
*
|
||||
* @param[in] aBegin A pointer to the begin of the range.
|
||||
* @param[in] aEnd A pointer to the end of the range, or nullptr to search all entries after @p aBegin.
|
||||
* @param[in] aIndicator An indicator to match with entries in the list.
|
||||
* @param[out] aPrevEntry A pointer to output the previous entry on success (when a match is found in the list).
|
||||
* @p aPrevEntry is set to nullptr if the matching entry is the head of the list. Otherwise
|
||||
* it is updated to point to the previous entry before the matching entry in the list.
|
||||
*
|
||||
* @returns A pointer to the matching entry if one is found, or nullptr if no matching entry was found.
|
||||
*
|
||||
*/
|
||||
template <typename Inidcator>
|
||||
const Type *FindMatching(const Type * aBegin,
|
||||
const Type * aEnd,
|
||||
const Inidcator &aIndicator,
|
||||
const Type *& aPrevEntry) const
|
||||
{
|
||||
const Type *entry;
|
||||
|
||||
aPrevEntry = nullptr;
|
||||
|
||||
for (entry = aBegin; entry != aEnd; aPrevEntry = entry, entry = entry->GetNext())
|
||||
{
|
||||
if (entry->Matches(aIndicator))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* This template method searches within a given range of the linked list to find an entry matching a given
|
||||
* indicator.
|
||||
*
|
||||
* The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries
|
||||
* in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each
|
||||
* `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly:
|
||||
*
|
||||
* bool Type::Matches(const Indicator &aIndicator) const
|
||||
*
|
||||
* @param[in] aBegin A pointer to the begin of the range.
|
||||
* @param[in] aEnd A pointer to the end of the range, or nullptr to search all entries after @p aBegin.
|
||||
* @param[in] aIndicator An indicator to match with entries in the list.
|
||||
* @param[out] aPrevEntry A pointer to output the previous entry on success (when a match is found in the list).
|
||||
* @p aPrevEntry is set to nullptr if the matching entry is the head of the list. Otherwise
|
||||
* it is updated to point to the previous entry before the matching entry in the list.
|
||||
*
|
||||
* @returns A pointer to the matching entry if one is found, or nullptr if no matching entry was found.
|
||||
*
|
||||
*/
|
||||
template <typename Inidcator>
|
||||
Type *FindMatching(const Type *aBegin, const Type *aEnd, const Inidcator &aIndicator, Type *&aPrevEntry)
|
||||
{
|
||||
return const_cast<Type *>(FindMatching(aBegin, aEnd, aIndicator, const_cast<const Type *&>(aPrevEntry)));
|
||||
}
|
||||
|
||||
/**
|
||||
* This template method searches within the linked list to find an entry matching a given indicator.
|
||||
*
|
||||
@@ -401,7 +468,7 @@ public:
|
||||
*
|
||||
* bool Type::Matches(const Indicator &aIndicator) const
|
||||
*
|
||||
* @param[in] aIndicator An indicator to match with entries in the list..
|
||||
* @param[in] aIndicator An indicator to match with entries in the list.
|
||||
* @param[out] aPrevEntry A pointer to output the previous entry on success (when a match is found in the list).
|
||||
* @p aPrevEntry is set to nullptr if the matching entry is the head of the list. Otherwise
|
||||
* it is updated to point to the previous entry before the matching entry in the list.
|
||||
@@ -411,19 +478,7 @@ public:
|
||||
*/
|
||||
template <typename Inidcator> const Type *FindMatching(const Inidcator &aIndicator, const Type *&aPrevEntry) const
|
||||
{
|
||||
const Type *entry;
|
||||
|
||||
aPrevEntry = nullptr;
|
||||
|
||||
for (entry = mHead; entry != nullptr; aPrevEntry = entry, entry = entry->GetNext())
|
||||
{
|
||||
if (entry->Matches(aIndicator))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return entry;
|
||||
return FindMatching(mHead, nullptr, aIndicator, aPrevEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -436,7 +491,7 @@ public:
|
||||
*
|
||||
* bool Type::Matches(const Indicator &aIndicator) const
|
||||
*
|
||||
* @param[in] aIndicator An indicator to match with entries in the list..
|
||||
* @param[in] aIndicator An indicator to match with entries in the list.
|
||||
* @param[out] aPrevEntry A pointer to output the previous entry on success (when a match is found in the list).
|
||||
* @p aPrevEntry is set to nullptr if the matching entry is the head of the list. Otherwise
|
||||
* it is updated to point to the previous entry before the matching entry in the list.
|
||||
|
||||
+90
-5
@@ -99,13 +99,26 @@ otError Udp::Socket::Bind(uint16_t aPort)
|
||||
return Bind(SockAddr(aPort));
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
||||
otError Udp::Socket::BindToNetif(otNetifIdentifier aNetifIdentifier)
|
||||
{
|
||||
return otPlatUdpBindToNetif(this, aNetifIdentifier);
|
||||
}
|
||||
OT_UNUSED_VARIABLE(aNetifIdentifier);
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
||||
SuccessOrExit(error = otPlatUdpBindToNetif(this, aNetifIdentifier));
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
Get<Udp>().BindToNetif(*this, aNetifIdentifier);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
||||
exit:
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Udp::Socket::Connect(const SockAddr &aSockAddr)
|
||||
{
|
||||
return Get<Udp>().Connect(*this, aSockAddr);
|
||||
@@ -131,6 +144,9 @@ Udp::Udp(Instance &aInstance)
|
||||
, mEphemeralPort(kDynamicPortMin)
|
||||
, mReceivers()
|
||||
, mSockets()
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
, mPrevBackboneSockets(nullptr)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
|
||||
, mUdpForwarderContext(nullptr)
|
||||
, mUdpForwarder(nullptr)
|
||||
@@ -204,6 +220,35 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
void Udp::BindToNetif(SocketHandle &aSocket, otNetifIdentifier aNetifIdentifier)
|
||||
{
|
||||
if (aNetifIdentifier == OT_NETIF_BACKBONE)
|
||||
{
|
||||
SetBackboneSocket(aSocket);
|
||||
}
|
||||
}
|
||||
|
||||
void Udp::SetBackboneSocket(SocketHandle &aSocket)
|
||||
{
|
||||
RemoveSocket(aSocket);
|
||||
|
||||
if (mPrevBackboneSockets != nullptr)
|
||||
{
|
||||
mSockets.PushAfter(aSocket, *mPrevBackboneSockets);
|
||||
}
|
||||
else
|
||||
{
|
||||
mSockets.Push(aSocket);
|
||||
}
|
||||
}
|
||||
|
||||
const Udp::SocketHandle *Udp::GetBackboneSockets(void)
|
||||
{
|
||||
return mPrevBackboneSockets != nullptr ? mPrevBackboneSockets->GetNext() : mSockets.GetHead();
|
||||
}
|
||||
#endif
|
||||
|
||||
otError Udp::Connect(SocketHandle &aSocket, const SockAddr &aSockAddr)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
@@ -296,14 +341,34 @@ exit:
|
||||
|
||||
void Udp::AddSocket(SocketHandle &aSocket)
|
||||
{
|
||||
IgnoreError(mSockets.Add(aSocket));
|
||||
SuccessOrExit(mSockets.Add(aSocket));
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
if (mPrevBackboneSockets == nullptr)
|
||||
{
|
||||
mPrevBackboneSockets = &aSocket;
|
||||
}
|
||||
#endif
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Udp::RemoveSocket(SocketHandle &aSocket)
|
||||
{
|
||||
SuccessOrExit(mSockets.Remove(aSocket));
|
||||
SocketHandle *prev;
|
||||
|
||||
SuccessOrExit(mSockets.Find(aSocket, prev));
|
||||
|
||||
mSockets.PopAfter(prev);
|
||||
aSocket.SetNext(nullptr);
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
if (&aSocket == mPrevBackboneSockets)
|
||||
{
|
||||
mPrevBackboneSockets = prev;
|
||||
}
|
||||
#endif
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
@@ -397,7 +462,27 @@ void Udp::HandlePayload(Message &aMessage, MessageInfo &aMessageInfo)
|
||||
SocketHandle *socket;
|
||||
SocketHandle *prev;
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
{
|
||||
const SocketHandle *socketsBegin, *socketsEnd;
|
||||
|
||||
if (!aMessageInfo.IsHostInterface())
|
||||
{
|
||||
socketsBegin = mSockets.GetHead();
|
||||
socketsEnd = GetBackboneSockets();
|
||||
}
|
||||
else
|
||||
{
|
||||
socketsBegin = GetBackboneSockets();
|
||||
socketsEnd = nullptr;
|
||||
}
|
||||
|
||||
socket = mSockets.FindMatching(socketsBegin, socketsEnd, aMessageInfo, prev);
|
||||
}
|
||||
#else
|
||||
socket = mSockets.FindMatching(aMessageInfo, prev);
|
||||
#endif
|
||||
|
||||
VerifyOrExit(socket != nullptr, OT_NOOP);
|
||||
|
||||
aMessage.RemoveHeader(aMessage.GetOffset());
|
||||
|
||||
+17
-2
@@ -177,7 +177,6 @@ public:
|
||||
*/
|
||||
otError Bind(const SockAddr &aSockAddr);
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
||||
/**
|
||||
* This method binds the UDP socket to a specified network interface.
|
||||
*
|
||||
@@ -188,7 +187,6 @@ public:
|
||||
*
|
||||
*/
|
||||
otError BindToNetif(otNetifIdentifier aNetifIdentifier);
|
||||
#endif // OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
||||
|
||||
/**
|
||||
* This method binds the UDP socket.
|
||||
@@ -438,6 +436,15 @@ public:
|
||||
*/
|
||||
otError Bind(SocketHandle &aSocket, const SockAddr &aSockAddr);
|
||||
|
||||
/**
|
||||
* This method binds a UDP socket to the Network interface.
|
||||
*
|
||||
* @param[in] aSocket A reference to the socket.
|
||||
* @param[in] aNetifIdentifier The network interface identifier.
|
||||
*
|
||||
*/
|
||||
void BindToNetif(SocketHandle &aSocket, otNetifIdentifier aNetifIdentifier);
|
||||
|
||||
/**
|
||||
* This method connects a UDP socket.
|
||||
*
|
||||
@@ -562,9 +569,17 @@ private:
|
||||
void RemoveSocket(SocketHandle &aSocket);
|
||||
bool IsMlePort(uint16_t aPort) const;
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
void SetBackboneSocket(SocketHandle &aSocket);
|
||||
const SocketHandle *GetBackboneSockets(void);
|
||||
#endif
|
||||
|
||||
uint16_t mEphemeralPort;
|
||||
LinkedList<Receiver> mReceivers;
|
||||
LinkedList<SocketHandle> mSockets;
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
SocketHandle *mPrevBackboneSockets;
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
|
||||
void * mUdpForwarderContext;
|
||||
otUdpForwarder mUdpForwarder;
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "backbone_router/bbr_leader.hpp"
|
||||
#endif
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
#include "backbone_router/backbone_tmf.hpp"
|
||||
#include "backbone_router/bbr_local.hpp"
|
||||
#include "backbone_router/bbr_manager.hpp"
|
||||
#endif
|
||||
|
||||
+1
-10
@@ -40,16 +40,7 @@ namespace Tmf {
|
||||
|
||||
otError TmfAgent::Start(void)
|
||||
{
|
||||
otError error;
|
||||
|
||||
SuccessOrExit(error = Coap::Start(kUdpPort));
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
||||
error = mSocket.BindToNetif(OT_NETIF_THREAD);
|
||||
VerifyOrExit(OT_ERROR_NONE == error, IgnoreError(mSocket.Close()));
|
||||
#endif
|
||||
|
||||
exit:
|
||||
return error;
|
||||
return Coap::Start(kUdpPort, OT_NETIF_THREAD);
|
||||
}
|
||||
|
||||
otError TmfAgent::Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext)
|
||||
|
||||
+30
-10
@@ -103,6 +103,9 @@ void __gcov_flush();
|
||||
*/
|
||||
enum
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
OT_POSIX_OPT_BACKBONE_INTERFACE_NAME = 'B',
|
||||
#endif
|
||||
OT_POSIX_OPT_DEBUG_LEVEL = 'd',
|
||||
OT_POSIX_OPT_DRY_RUN = 'n',
|
||||
OT_POSIX_OPT_HELP = 'h',
|
||||
@@ -116,15 +119,19 @@ enum
|
||||
OT_POSIX_OPT_REAL_TIME_SIGNAL,
|
||||
};
|
||||
|
||||
static const struct option kOptions[] = {{"debug-level", required_argument, NULL, OT_POSIX_OPT_DEBUG_LEVEL},
|
||||
{"dry-run", no_argument, NULL, OT_POSIX_OPT_DRY_RUN},
|
||||
{"help", no_argument, NULL, OT_POSIX_OPT_HELP},
|
||||
{"interface-name", required_argument, NULL, OT_POSIX_OPT_INTERFACE_NAME},
|
||||
{"radio-version", no_argument, NULL, OT_POSIX_OPT_RADIO_VERSION},
|
||||
{"real-time-signal", required_argument, NULL, OT_POSIX_OPT_REAL_TIME_SIGNAL},
|
||||
{"time-speed", required_argument, NULL, OT_POSIX_OPT_TIME_SPEED},
|
||||
{"verbose", no_argument, NULL, OT_POSIX_OPT_VERBOSE},
|
||||
{0, 0, 0, 0}};
|
||||
static const struct option kOptions[] = {
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
{"backbone-interface-name", required_argument, NULL, OT_POSIX_OPT_BACKBONE_INTERFACE_NAME},
|
||||
#endif
|
||||
{"debug-level", required_argument, NULL, OT_POSIX_OPT_DEBUG_LEVEL},
|
||||
{"dry-run", no_argument, NULL, OT_POSIX_OPT_DRY_RUN},
|
||||
{"help", no_argument, NULL, OT_POSIX_OPT_HELP},
|
||||
{"interface-name", required_argument, NULL, OT_POSIX_OPT_INTERFACE_NAME},
|
||||
{"radio-version", no_argument, NULL, OT_POSIX_OPT_RADIO_VERSION},
|
||||
{"real-time-signal", required_argument, NULL, OT_POSIX_OPT_REAL_TIME_SIGNAL},
|
||||
{"time-speed", required_argument, NULL, OT_POSIX_OPT_TIME_SPEED},
|
||||
{"verbose", no_argument, NULL, OT_POSIX_OPT_VERBOSE},
|
||||
{0, 0, 0, 0}};
|
||||
|
||||
static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode)
|
||||
{
|
||||
@@ -132,6 +139,9 @@ static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode)
|
||||
"Syntax:\n"
|
||||
" %s [Options] RadioURL\n"
|
||||
"Options:\n"
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
" -B --backbone-interface-name Backbone network interface name.\n"
|
||||
#endif
|
||||
" -d --debug-level Debug level of logging.\n"
|
||||
" -h --help Display this usage information.\n"
|
||||
" -I --interface-name name Thread network interface name.\n"
|
||||
@@ -165,7 +175,12 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig)
|
||||
while (true)
|
||||
{
|
||||
int index = 0;
|
||||
int option = getopt_long(aArgCount, aArgVector, "d:hI:ns:v", kOptions, &index);
|
||||
int option = getopt_long(aArgCount, aArgVector,
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
"B:"
|
||||
#endif
|
||||
"d:hI:ns:v",
|
||||
kOptions, &index);
|
||||
|
||||
if (option == -1)
|
||||
{
|
||||
@@ -183,6 +198,11 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig)
|
||||
case OT_POSIX_OPT_INTERFACE_NAME:
|
||||
aConfig->mPlatformConfig.mInterfaceName = optarg;
|
||||
break;
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
case OT_POSIX_OPT_BACKBONE_INTERFACE_NAME:
|
||||
aConfig->mPlatformConfig.mBackboneInterfaceName = optarg;
|
||||
break;
|
||||
#endif
|
||||
case OT_POSIX_OPT_DRY_RUN:
|
||||
aConfig->mIsDryRun = true;
|
||||
break;
|
||||
|
||||
@@ -61,6 +61,7 @@ list(APPEND OT_PLATFORM_DEFINES "OPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"${OT_CONF
|
||||
|
||||
add_library(openthread-posix
|
||||
alarm.cpp
|
||||
backbone.cpp
|
||||
entropy.cpp
|
||||
hdlc_interface.cpp
|
||||
logging.cpp
|
||||
|
||||
@@ -45,6 +45,7 @@ libopenthread_posix_a_CPPFLAGS = \
|
||||
|
||||
libopenthread_posix_a_SOURCES = \
|
||||
alarm.cpp \
|
||||
backbone.cpp \
|
||||
entropy.cpp \
|
||||
hdlc_interface.cpp \
|
||||
logging.cpp \
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2020, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the platform Backbone interface management on Linux.
|
||||
*/
|
||||
|
||||
#include "openthread-posix-config.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
|
||||
#include "platform-posix.h"
|
||||
#include "common/code_utils.hpp"
|
||||
|
||||
char gBackboneNetifName[IFNAMSIZ] = "";
|
||||
unsigned int gBackboneNetifIndex = 0;
|
||||
|
||||
void platformBackboneInit(otInstance *aInstance, const char *aInterfaceName)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
VerifyOrExit(aInterfaceName != nullptr, OT_NOOP);
|
||||
|
||||
VerifyOrDie(strnlen(aInterfaceName, IFNAMSIZ) <= IFNAMSIZ - 1, OT_EXIT_INVALID_ARGUMENTS);
|
||||
strcpy(gBackboneNetifName, aInterfaceName);
|
||||
|
||||
gBackboneNetifIndex = if_nametoindex(gBackboneNetifName);
|
||||
VerifyOrDie(gBackboneNetifIndex > 0, OT_EXIT_FAILURE);
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -70,10 +70,11 @@ enum
|
||||
*/
|
||||
typedef struct otPlatformConfig
|
||||
{
|
||||
const char *mInterfaceName; ///< Thread network interface name.
|
||||
const char *mRadioUrl; ///< Radio url.
|
||||
int mRealTimeSignal; ///< The real-time signal for microsecond timer.
|
||||
uint32_t mSpeedUpFactor; ///< Speed up factor.
|
||||
const char *mBackboneInterfaceName; ///< Backbone network interface name.
|
||||
const char *mInterfaceName; ///< Thread network interface name.
|
||||
const char *mRadioUrl; ///< Radio url.
|
||||
int mRealTimeSignal; ///< The real-time signal for microsecond timer.
|
||||
uint32_t mSpeedUpFactor; ///< Speed up factor.
|
||||
} otPlatformConfig;
|
||||
|
||||
/**
|
||||
|
||||
@@ -407,6 +407,29 @@ extern char gNetifName[IFNAMSIZ];
|
||||
*/
|
||||
extern unsigned int gNetifIndex;
|
||||
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
/**
|
||||
* This function initializes platform Backbone network.
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
* @param[in] aInterfaceName A pointer to Thread network interface name.
|
||||
*
|
||||
*/
|
||||
void platformBackboneInit(otInstance *aInstance, const char *aInterfaceName);
|
||||
|
||||
/**
|
||||
* The name of Backbone network interface.
|
||||
*
|
||||
*/
|
||||
extern char gBackboneNetifName[IFNAMSIZ];
|
||||
|
||||
/**
|
||||
* The index of Backbone network interface.
|
||||
*
|
||||
*/
|
||||
extern unsigned int gBackboneNetifIndex;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -63,6 +63,10 @@ otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
|
||||
instance = otInstanceInitSingle();
|
||||
assert(instance != nullptr);
|
||||
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
platformBackboneInit(instance, aPlatformConfig->mBackboneInterfaceName);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
|
||||
platformNetifInit(instance, aPlatformConfig->mInterfaceName);
|
||||
#elif OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
||||
|
||||
@@ -276,9 +276,6 @@ otError otPlatUdpBind(otUdpSocket *aUdpSocket)
|
||||
VerifyOrExit(0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)), error = OT_ERROR_FAILED);
|
||||
}
|
||||
|
||||
VerifyOrExit(0 == setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &gNetifIndex, sizeof(gNetifIndex)),
|
||||
error = OT_ERROR_FAILED);
|
||||
|
||||
exit:
|
||||
if (error == OT_ERROR_FAILED)
|
||||
{
|
||||
@@ -316,6 +313,21 @@ otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifId
|
||||
#endif // __linux__
|
||||
break;
|
||||
}
|
||||
case OT_NETIF_BACKBONE:
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
#if __linux__
|
||||
VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, gBackboneNetifName, strlen(gBackboneNetifName)) == 0,
|
||||
error = OT_ERROR_FAILED);
|
||||
#else // __NetBSD__ || __FreeBSD__ || __APPLE__
|
||||
VerifyOrExit(setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &gBackboneNetifIndex, sizeof(gBackboneNetifIndex)),
|
||||
error = OT_ERROR_FAILED);
|
||||
#endif // __linux__
|
||||
#else
|
||||
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
Reference in New Issue
Block a user