[mesh-forwarder] add support for Neighbor Discovery Agent Anycast (#6423)

This commit is contained in:
Jonathan Hui
2021-04-07 22:22:12 -07:00
parent 8959216641
commit fa99680f02
21 changed files with 309 additions and 10 deletions

View File

@ -278,6 +278,7 @@ LOCAL_SRC_FILES := \
src/core/net/ip6_filter.cpp \
src/core/net/ip6_headers.cpp \
src/core/net/ip6_mpl.cpp \
src/core/net/nd_agent.cpp \
src/core/net/netif.cpp \
src/core/net/sntp_client.cpp \
src/core/net/socket.cpp \

View File

@ -257,6 +257,11 @@ if(OT_MULTIPLE_INSTANCE)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE=1")
endif()
option(OT_NEIGHBOR_DISCOVERY_AGENT "enable neighbor discovery agent support")
if(OT_NEIGHBOR_DISCOVERY_AGENT)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE=1")
endif()
option(OT_PING_SENDER "enable ping sender support" ${OT_APP_CLI})
if(OT_PING_SENDER)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_PING_SENDER_ENABLE=1")

View File

@ -59,6 +59,7 @@ LEGACY ?= 1
LINK_RAW ?= 1
MAC_FILTER ?= 1
MTD_NETDIAG ?= 1
NEIGHBOR_DISCOVERY_AGENT ?= 1
PING_SENDER ?= 1
REFERENCE_DEVICE ?= 1
SERVICE ?= 1

View File

@ -69,6 +69,7 @@ MLE_LONG_ROUTES ?= 0
MLR ?= 0
MTD_NETDIAG ?= 0
MULTIPLE_INSTANCE ?= 0
NEIGHBOR_DISCOVERY_AGENT ?= 0
OTNS ?= 0
PING_SENDER ?= 1
PLATFORM_UDP ?= 0
@ -256,6 +257,10 @@ ifeq ($(MULTIPLE_INSTANCE),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE=1
endif
ifeq ($(NEIGHBOR_DISCOVERY_AGENT),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE=1
endif
ifeq ($(PING_SENDER),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_PING_SENDER_ENABLE=1
endif

View File

@ -68,6 +68,7 @@ do_scan_build()
"-DOPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_ENABLE=1"
"-DOPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE=1"
"-DOPENTHREAD_CONFIG_MPL_DYNAMIC_INTERVAL_ENABLE"
"-DOPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT=1"
"-DOPENTHREAD_CONFIG_PING_SENDER_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE=1"

View File

@ -104,6 +104,7 @@ readonly OT_POSIX_SIM_COMMON_OPTIONS=(
"-DOT_LEGACY=ON"
"-DOT_MAC_FILTER=ON"
"-DOT_MTD_NETDIAG=ON"
"-DOT_NEIGHBOR_DISCOVERY_AGENT=ON"
"-DOT_PING_SENDER=ON"
"-DOT_REFERENCE_DEVICE=ON"
"-DOT_SERVICE=ON"

View File

@ -506,6 +506,8 @@ openthread_core_files = [
"net/ip6_headers.hpp",
"net/ip6_mpl.cpp",
"net/ip6_mpl.hpp",
"net/nd_agent.cpp",
"net/nd_agent.hpp",
"net/netif.cpp",
"net/netif.hpp",
"net/sntp_client.cpp",

View File

@ -153,6 +153,7 @@ set(COMMON_SOURCES
net/ip6_filter.cpp
net/ip6_headers.cpp
net/ip6_mpl.cpp
net/nd_agent.cpp
net/netif.cpp
net/sntp_client.cpp
net/socket.cpp

View File

@ -230,6 +230,7 @@ SOURCES_COMMON = \
net/ip6_filter.cpp \
net/ip6_headers.cpp \
net/ip6_mpl.cpp \
net/nd_agent.cpp \
net/netif.cpp \
net/sntp_client.cpp \
net/socket.cpp \
@ -486,6 +487,7 @@ HEADERS_COMMON = \
net/ip6_filter.hpp \
net/ip6_headers.hpp \
net/ip6_mpl.hpp \
net/nd_agent.hpp \
net/netif.hpp \
net/sntp_client.hpp \
net/socket.hpp \

View File

@ -752,6 +752,13 @@ template <> inline Dhcp6::Server &Instance::Get(void)
}
#endif
#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
template <> inline NeighborDiscovery::Agent &Instance::Get(void)
{
return mThreadNetif.mNeighborDiscoveryAgent;
}
#endif
#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
template <> inline Utils::Slaac &Instance::Get(void)
{

View File

@ -493,4 +493,14 @@
#define OPENTHREAD_CONFIG_MLR_ENABLE 0
#endif
/**
* @def OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
*
* Define as 1 to enable support for Neighbor Discover Agent.
*
*/
#ifndef OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
#define OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE 0
#endif
#endif // OPENTHREAD_CORE_DEFAULT_CONFIG_H_

133
src/core/net/nd_agent.cpp Normal file
View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2021, 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 IPv6 Neighbor Discovery Agent.
*/
#include "nd_agent.hpp"
#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
#include "common/locator_getters.hpp"
#include "thread/lowpan.hpp"
#include "thread/mle_router.hpp"
#include "thread/network_data_leader.hpp"
#include "thread/thread_netif.hpp"
namespace ot {
namespace NeighborDiscovery {
void Agent::UpdateService(void)
{
Error error;
uint16_t rloc16 = Get<Mle::MleRouter>().GetRloc16();
NetworkData::Iterator iterator;
NetworkData::OnMeshPrefixConfig config;
Lowpan::Context lowpanContext;
if (IsAlocInUse())
{
uint8_t contextId = static_cast<uint8_t>(mAloc.GetAddress().GetIid().GetLocator() -
Mle::kAloc16NeighborDiscoveryAgentStart + 1);
bool found = false;
iterator = NetworkData::kIteratorInit;
while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, rloc16, config) == kErrorNone)
{
if (!config.mNdDns)
{
continue;
}
error = Get<NetworkData::Leader>().GetContext(static_cast<const Ip6::Address &>(config.mPrefix.mPrefix),
lowpanContext);
if ((error != kErrorNone) || (lowpanContext.mContextId != contextId))
{
continue;
}
found = true;
break;
}
if (!found)
{
Get<ThreadNetif>().RemoveUnicastAddress(mAloc);
FreeAloc();
}
}
VerifyOrExit(!IsAlocInUse());
iterator = NetworkData::kIteratorInit;
while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, rloc16, config) == kErrorNone)
{
if (!config.mNdDns)
{
continue;
}
error = Get<NetworkData::Leader>().GetContext(static_cast<const Ip6::Address &>(config.mPrefix.mPrefix),
lowpanContext);
if (error == kErrorNone)
{
uint16_t rloc = Mle::kAloc16NeighborDiscoveryAgentStart + lowpanContext.mContextId - 1;
mAloc.InitAsThreadOrigin();
mAloc.GetAddress().SetToAnycastLocator(Get<Mle::MleRouter>().GetMeshLocalPrefix(), rloc);
Get<ThreadNetif>().AddUnicastAddress(mAloc);
ExitNow();
}
}
exit:
return;
}
void Agent::ApplyMeshLocalPrefix(void)
{
VerifyOrExit(IsAlocInUse());
Get<ThreadNetif>().RemoveUnicastAddress(mAloc);
mAloc.GetAddress().SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
Get<ThreadNetif>().AddUnicastAddress(mAloc);
exit:
return;
}
} // namespace NeighborDiscovery
} // namespace ot
#endif // OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE

87
src/core/net/nd_agent.hpp Normal file
View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2021, 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 IPv6 Neighbor Discovery Agent.
*/
#ifndef NEIGHBOR_DISCOVERY_AGENT_HPP_
#define NEIGHBOR_DISCOVERY_AGENT_HPP_
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "net/netif.hpp"
namespace ot {
namespace NeighborDiscovery {
class Agent : public InstanceLocator, private NonCopyable
{
public:
/**
* This constructor initializes the object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit Agent(Instance &aInstance)
: InstanceLocator(aInstance)
{
FreeAloc();
}
/**
* This method updates the Neighbor Discovery Agents using current Thread Network Data.
*
*/
void UpdateService(void);
/**
* This method updates the prefix of the Neighbor Discovery Agent Anycast Locator.
*
*/
void ApplyMeshLocalPrefix(void);
private:
void FreeAloc(void) { mAloc.mNext = &mAloc; }
bool IsAlocInUse(void) const { return mAloc.mNext != &mAloc; }
Ip6::NetifUnicastAddress mAloc;
};
} // namespace NeighborDiscovery
} // namespace ot
#endif // OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
#endif // NEIGHBOR_DISCOVERY_AGENT_HPP_

View File

@ -339,6 +339,12 @@ private:
kMessageEvict, ///< Indicates that the message was evicted.
};
enum AnycastType : uint8_t
{
kAnycastDhcp6Agent,
kAnycastNeighborDiscoveryAgent,
};
#if OPENTHREAD_FTD
class FragmentPriorityList : public Clearable<FragmentPriorityList>
{
@ -440,7 +446,7 @@ private:
void SendDestinationUnreachable(uint16_t aMeshSource, const Message &aMessage);
Error UpdateIp6Route(Message &aMessage);
Error UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessage);
Error ContextIdRouteLookup(uint8_t aContextId, uint16_t &aMeshDest) const;
Error ContextIdRouteLookup(uint8_t aContextId, AnycastType aType, uint16_t &aMeshDest) const;
Error UpdateMeshRoute(Message &aMessage);
bool UpdateReassemblyList(void);
void UpdateFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader,

View File

@ -402,7 +402,7 @@ exit:
return error;
}
Error MeshForwarder::ContextIdRouteLookup(uint8_t aContextId, uint16_t &aMeshDest) const
Error MeshForwarder::ContextIdRouteLookup(uint8_t aContextId, AnycastType aType, uint16_t &aMeshDest) const
{
Lowpan::Context context;
NetworkData::Iterator iterator = NetworkData::kIteratorInit;
@ -424,6 +424,22 @@ Error MeshForwarder::ContextIdRouteLookup(uint8_t aContextId, uint16_t &aMeshDes
continue;
}
switch (aType)
{
case kAnycastDhcp6Agent:
if (!(config.mDhcp || config.mConfigure))
{
continue;
}
break;
case kAnycastNeighborDiscoveryAgent:
if (!config.mNdDns)
{
continue;
}
break;
}
// Path cost
curCost = Get<Mle::MleRouter>().GetCost(server16);
@ -507,8 +523,8 @@ Error MeshForwarder::UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessage
}
else if (aloc16 <= Mle::kAloc16DhcpAgentEnd)
{
uint8_t contextId = static_cast<uint8_t>(aloc16 & Mle::kAloc16DhcpAgentMask);
SuccessOrExit(error = ContextIdRouteLookup(contextId, mMeshDest));
uint8_t contextId = static_cast<uint8_t>(aloc16 - Mle::kAloc16DhcpAgentStart + 1);
SuccessOrExit(error = ContextIdRouteLookup(contextId, kAnycastDhcp6Agent, mMeshDest));
}
else if (aloc16 <= Mle::kAloc16ServiceEnd)
{
@ -526,9 +542,14 @@ Error MeshForwarder::UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessage
mMeshDest = Get<BackboneRouter::Leader>().GetServer16();
}
#endif
else if ((aloc16 >= Mle::kAloc16NeighborDiscoveryAgentStart) &&
(aloc16 <= Mle::kAloc16NeighborDiscoveryAgentEnd))
{
uint8_t contextId = static_cast<uint8_t>(aloc16 - Mle::kAloc16NeighborDiscoveryAgentStart + 1);
SuccessOrExit(error = ContextIdRouteLookup(contextId, kAnycastNeighborDiscoveryAgent, mMeshDest));
}
else
{
// TODO: support for Neighbor Discovery Agent ALOC
ExitNow(error = kErrorDrop);
}
}

View File

@ -858,6 +858,10 @@ void Mle::ApplyMeshLocalPrefix(void)
Get<Dhcp6::Server>().ApplyMeshLocalPrefix();
#endif
#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
Get<NeighborDiscovery::Agent>().ApplyMeshLocalPrefix();
#endif
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
for (Ip6::NetifUnicastAddress &serviceAloc : mServiceAlocs)
@ -1556,11 +1560,15 @@ void Mle::HandleNotifierEvents(Events aEvents)
#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
IgnoreError(Get<Dhcp6::Server>().UpdateService());
#endif // OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
#endif
#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
Get<NeighborDiscovery::Agent>().UpdateService();
#endif
#if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
Get<Dhcp6::Client>().UpdateAddresses();
#endif // OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
#endif
}
if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadKeySeqCounterChanged))

View File

@ -235,7 +235,6 @@ enum AlocAllocation
kAloc16Leader = 0xfc00,
kAloc16DhcpAgentStart = 0xfc01,
kAloc16DhcpAgentEnd = 0xfc0f,
kAloc16DhcpAgentMask = 0x000f,
kAloc16ServiceStart = 0xfc10,
kAloc16ServiceEnd = 0xfc2f,
kAloc16CommissionerStart = 0xfc30,

View File

@ -56,6 +56,9 @@ ThreadNetif::ThreadNetif(Instance &aInstance)
#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
, mDhcp6Server(aInstance)
#endif
#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
, mNeighborDiscoveryAgent(aInstance)
#endif
#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
, mSlaac(aInstance)
#endif

View File

@ -82,6 +82,7 @@
#include "net/dns_client.hpp"
#include "net/dnssd_server.hpp"
#include "net/ip6_filter.hpp"
#include "net/nd_agent.hpp"
#include "net/netif.hpp"
#include "net/sntp_client.hpp"
#include "net/srp_client.hpp"
@ -195,10 +196,13 @@ private:
Tmf::TmfAgent mTmfAgent;
#if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
Dhcp6::Client mDhcp6Client;
#endif // OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
#endif
#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
Dhcp6::Server mDhcp6Server;
#endif // OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
#endif
#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
NeighborDiscovery::Agent mNeighborDiscoveryAgent;
#endif
#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
Utils::Slaac mSlaac;
#endif

View File

@ -62,6 +62,7 @@ LOG_OUTPUT ?= PLATFORM_DEFINED
MAC_FILTER ?= 1
MAX_POWER_TABLE ?= 1
MTD_NETDIAG ?= 1
NEIGHBOR_DISCOVERY_AGENT ?= 1
PING_SENDER ?= 1
READLINE ?= readline
REFERENCE_DEVICE ?= 1

View File

@ -93,6 +93,7 @@ class TestAnycast(thread_cert.TestCase):
self.__test('ds') # DHCPv6 Agent (IPv6 Address)
self.__test('cs') # DHCPv6 Agent (Other)
self.__test('ns') # Neighbor Discovery Agent
def __test(self, borderRouterFlags):
# Single Server