diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ac6b27f6628..2ae58a45147 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -169,9 +169,14 @@ jobs: submodules: true - name: Build OTBR Docker Image run: | - otbr_options="-DOTBR_BACKBONE_ROUTER=ON -DOT_DUA=ON -DOT_MLR=ON -DOTBR_COVERAGE=ON" + otbr_options="-DOT_DUA=ON -DOT_MLR=ON -DOTBR_COVERAGE=ON" otbr_image_name="otbr-ot12-backbone-ci" - docker build -t "${otbr_image_name}" -f etc/docker/Dockerfile . --build-arg REFERENCE_DEVICE=1 --build-arg OT_BACKBONE_CI=1 --build-arg OTBR_OPTIONS="${otbr_options}" + docker build -t "${otbr_image_name}" -f etc/docker/Dockerfile . \ + --build-arg BACKBONE_ROUTER=1 \ + --build-arg REFERENCE_DEVICE=${REFERENCE_DEVICE} \ + --build-arg OT_BACKBONE_CI=1 \ + --build-arg NAT64=0 \ + --build-arg OTBR_OPTIONS="${otbr_options}" - name: Bootstrap OpenThread Test run: | sudo rm /etc/apt/sources.list.d/* && sudo apt-get update diff --git a/Android.mk b/Android.mk index e89bae9a9eb..3cd4b01310c 100644 --- a/Android.mk +++ b/Android.mk @@ -92,6 +92,7 @@ LOCAL_CPPFLAGS += -std=c++14 LOCAL_SRC_FILES := \ src/agent/agent_instance.cpp \ + src/agent/instance_params.cpp \ src/agent/border_agent.cpp \ src/agent/main.cpp \ src/agent/ncp_openthread.cpp \ diff --git a/etc/docker/Dockerfile b/etc/docker/Dockerfile index e2955bd1c0f..25e328ae9c6 100644 --- a/etc/docker/Dockerfile +++ b/etc/docker/Dockerfile @@ -27,6 +27,7 @@ FROM ubuntu:focal +ARG BACKBONE_ROUTER ARG OT_BACKBONE_CI ARG OTBR_OPTIONS ARG DNS64 @@ -34,6 +35,7 @@ ARG NAT64 ARG REFERENCE_DEVICE ARG RELEASE +ENV BACKBONE_ROUTER=${BACKBONE_ROUTER:-0} ENV OT_BACKBONE_CI=${OT_BACKBONE_CI:-0} ENV OTBR_OPTIONS=${OTBR_OPTIONS} ENV DEBIAN_FRONTEND noninteractive @@ -58,7 +60,8 @@ ENV OTBR_DOCKER_DEPS git ca-certificates # Required and installed during build (script/bootstrap), could be removed ENV OTBR_BUILD_DEPS apt-utils build-essential psmisc ninja-build cmake wget ca-certificates \ libreadline-dev libncurses-dev libcpputest-dev libdbus-1-dev libavahi-common-dev \ - libavahi-client-dev libboost-dev libboost-filesystem-dev libboost-system-dev libjsoncpp-dev + libavahi-client-dev libboost-dev libboost-filesystem-dev libboost-system-dev libjsoncpp-dev \ + autoconf automake pkg-config # Required for OpenThread Backbone CI ENV OTBR_OT_BACKBONE_CI_DEPS curl lcov diff --git a/examples/platforms/beagleboneblack/default b/examples/platforms/beagleboneblack/default index 6fe536ae60a..192d241f80d 100644 --- a/examples/platforms/beagleboneblack/default +++ b/examples/platforms/beagleboneblack/default @@ -38,3 +38,4 @@ DHCPV6_PD=1 NETWORK_MANAGER=1 # disabled unless specifically added for the device NETWORK_MANAGER_WIFI=0 +BACKBONE_ROUTER=0 diff --git a/examples/platforms/fedora/default b/examples/platforms/fedora/default index 7c4468e7316..1d732f78ded 100644 --- a/examples/platforms/fedora/default +++ b/examples/platforms/fedora/default @@ -32,3 +32,4 @@ NAT64=0 DNS64=0 DHCPV6_PD=0 NETWORK_MANAGER=0 +BACKBONE_ROUTER=0 diff --git a/examples/platforms/raspbian/default b/examples/platforms/raspbian/default index bc8dce30cbe..7e518a4a442 100644 --- a/examples/platforms/raspbian/default +++ b/examples/platforms/raspbian/default @@ -32,3 +32,4 @@ NAT64=1 DNS64=1 DHCPV6_PD=1 NETWORK_MANAGER=1 +BACKBONE_ROUTER=0 diff --git a/examples/platforms/ubuntu/default b/examples/platforms/ubuntu/default index fce15a150e1..7f7b5d4adc9 100644 --- a/examples/platforms/ubuntu/default +++ b/examples/platforms/ubuntu/default @@ -32,3 +32,4 @@ NAT64=1 DNS64=1 DHCPV6_PD=0 NETWORK_MANAGER=0 +BACKBONE_ROUTER=0 diff --git a/script/_otbr b/script/_otbr index 4392276e2c8..772fd752539 100644 --- a/script/_otbr +++ b/script/_otbr @@ -30,7 +30,8 @@ readonly OTBR_TOP_BUILDDIR="${BUILD_DIR}/otbr" readonly OTBR_TOP_SRCDIR="$PWD" readonly OTBR_OPTIONS="${OTBR_OPTIONS:-}" -readonly REFERENCE_DEVICE=${REFERENCE_DEVICE:-0} +readonly REFERENCE_DEVICE="${REFERENCE_DEVICE:-0}" +readonly BACKBONE_ROUTER="${BACKBONE_ROUTER:-0}" otbr_uninstall() { @@ -53,13 +54,6 @@ otbr_uninstall() fi } -install_reference_device_deps() -{ - with REFERENCE_DEVICE || return 0 - - sudo apt-get install -y --no-install-recommends radvd -} - otbr_install() { local otbr_options=() @@ -82,6 +76,11 @@ otbr_install() "-DOT_REFERENCE_DEVICE=ON" ) fi + if [[ ${BACKBONE_ROUTER} == "1" ]]; then + otbr_options+=( + "-DOTBR_BACKBONE_ROUTER=ON" + ) + fi (mkdir -p "${OTBR_TOP_BUILDDIR}" \ && cd "${OTBR_TOP_BUILDDIR}" \ @@ -98,8 +97,6 @@ otbr_install() else echo >&2 ' *** WARNING: systemctl not found. otbr cannot start on boot.' fi - - install_reference_device_deps } otbr_update() diff --git a/script/_smcroute b/script/_smcroute new file mode 100644 index 00000000000..714c764bfde --- /dev/null +++ b/script/_smcroute @@ -0,0 +1,59 @@ +#!/bin/bash +# +# 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. +# +# Description: +# This script manipulates smcroute configuration. +# + +smcroute_uninstall() +{ + with BACKBONE_ROUTER || return 0 + + sudo smcroutectl kill || true + + test -d "$BUILD_DIR"/smcroute || return 0 + + (cd "$BUILD_DIR"/smcroute \ + && (test ! -f config.status || sudo make uninstall)) +} + +smcroute_install() +{ + with BACKBONE_ROUTER || return 0 + + test -d "$BUILD_DIR"/smcroute || (cd "$BUILD_DIR" \ + && git clone -b ip6_mf --depth 1 https://github.com/librasungirl/smcroute.git) || die 'Failed to download source code of SMCRoute!' + + ( + cd "$BUILD_DIR"/smcroute || return 1 + test -f configure || ./autogen.sh + test -f config.status || ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var + make + sudo make install + ) +} diff --git a/script/bootstrap b/script/bootstrap index 3f3cb6de5a4..dae7d568581 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -43,7 +43,7 @@ install_packages_apt() libreadline-dev \ libncurses-dev - sudo apt-get install --no-install-recommends -y build-essential ninja-build cmake + sudo apt-get install --no-install-recommends -y build-essential ninja-build cmake automake autoconf pkg-config with RELEASE || sudo apt-get install --no-install-recommends -y libcpputest-dev @@ -86,6 +86,9 @@ install_packages_apt() # libjsoncpp sudo apt-get install --no-install-recommends -y libjsoncpp1 libjsoncpp-dev + + # reference device + without REFERENCE_DEVICE || sudo apt-get install --no-install-recommends -y radvd } install_packages_opkg() @@ -100,7 +103,7 @@ install_packages_rpm() else PM=yum fi - sudo $PM install -y gcc gcc-c++ + sudo $PM install -y gcc gcc-c++ automake autoconf pkg-config with RELEASE || sudo $PM install -y cmake ninja-build sudo $PM install -y dbus-devel sudo $PM install -y avahi avahi-devel diff --git a/script/setup b/script/setup index 480db78b6e9..2a77dcbada1 100755 --- a/script/setup +++ b/script/setup @@ -38,6 +38,7 @@ . script/_dns64 . script/_dhcpv6_pd . script/_network_manager +. script/_smcroute . script/_swapfile . script/_sudo_extend . script/_disable_services @@ -53,9 +54,11 @@ main() dhcpv6_pd_uninstall nat64_uninstall dns64_uninstall + smcroute_uninstall ipforward_uninstall ipforward_install + smcroute_install nat64_install dns64_install network_manager_install diff --git a/script/update b/script/update index a920f54929d..698e409a915 100755 --- a/script/update +++ b/script/update @@ -38,6 +38,7 @@ . script/_nat64 . script/_dns64 . script/_dhcpv6_pd +. script/_smcroute main() { @@ -48,9 +49,11 @@ main() dhcpv6_pd_uninstall nat64_uninstall dns64_uninstall + smcroute_uninstall ipforward_uninstall ipforward_install + smcroute_install nat64_install dns64_install dhcpv6_pd_install diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 21a5c199522..e9c186b94cb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -51,3 +51,6 @@ if(OTBR_REST) add_subdirectory(rest) endif() +if (OTBR_BACKBONE_ROUTER) + add_subdirectory(backbone_router) +endif() diff --git a/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt index 99236a5b888..4ddb760d03a 100644 --- a/src/agent/CMakeLists.txt +++ b/src/agent/CMakeLists.txt @@ -38,6 +38,8 @@ add_executable(otbr-agent ncp_openthread.hpp thread_helper.cpp thread_helper.hpp + instance_params.cpp + instance_params.hpp ) target_link_libraries(otbr-agent PRIVATE @@ -45,6 +47,7 @@ target_link_libraries(otbr-agent PRIVATE $<$:otbr-mdns> $<$:otbr-ubus> $<$:otbr-rest> + $<$:otbr-backbone-router> openthread-cli-ftd openthread-ftd openthread-posix diff --git a/src/agent/agent_instance.cpp b/src/agent/agent_instance.cpp index 1fd7962e32c..b84fca0dca6 100644 --- a/src/agent/agent_instance.cpp +++ b/src/agent/agent_instance.cpp @@ -55,7 +55,7 @@ otbrError AgentInstance::Init(void) mBorderAgent.Init(); exit: - otbrLogResult("Initialize OpenThread Border Router Agent", error); + otbrLogResult(error, "Initialize OpenThread Border Router Agent"); return error; } diff --git a/src/agent/agent_instance.hpp b/src/agent/agent_instance.hpp index 27853de8a26..950a699b10c 100644 --- a/src/agent/agent_instance.hpp +++ b/src/agent/agent_instance.hpp @@ -42,6 +42,7 @@ #include #include "agent/border_agent.hpp" +#include "agent/instance_params.hpp" #include "agent/ncp.hpp" namespace otbr { diff --git a/src/agent/border_agent.cpp b/src/agent/border_agent.cpp index 9df1fb5ffd1..49a39890a55 100644 --- a/src/agent/border_agent.cpp +++ b/src/agent/border_agent.cpp @@ -46,6 +46,7 @@ #include "agent/border_agent.hpp" #include "agent/ncp.hpp" +#include "agent/ncp_openthread.hpp" #include "agent/uris.hpp" #include "common/code_utils.hpp" #include "common/logging.hpp" @@ -87,6 +88,9 @@ BorderAgent::BorderAgent(Ncp::Controller *aNcp) : mPublisher(nullptr) #endif , mNcp(aNcp) +#if OTBR_ENABLE_BACKBONE_ROUTER + , mBackboneAgent(*reinterpret_cast(aNcp)) +#endif , mThreadStarted(false) { } @@ -106,8 +110,12 @@ void BorderAgent::Init(void) mNcp->On(Ncp::kEventThreadState, HandleThreadState, this); mNcp->On(Ncp::kEventPSKc, HandlePSKc, this); - otbrLogResult("Check if Thread is up", mNcp->RequestEvent(Ncp::kEventThreadState)); - otbrLogResult("Check if PSKc is initialized", mNcp->RequestEvent(Ncp::kEventPSKc)); +#if OTBR_ENABLE_BACKBONE_ROUTER + mBackboneAgent.Init(); +#endif + + otbrLogResult(mNcp->RequestEvent(Ncp::kEventThreadState), "Check if Thread is up"); + otbrLogResult(mNcp->RequestEvent(Ncp::kEventPSKc), "Check if PSKc is initialized"); } otbrError BorderAgent::Start(void) @@ -131,7 +139,7 @@ otbrError BorderAgent::Start(void) ExitNow(); exit: - otbrLogResult("Start Thread Border Agent", error); + otbrLogResult(error, "Start Thread Border Agent"); return error; } diff --git a/src/agent/border_agent.hpp b/src/agent/border_agent.hpp index ae58a4fde00..96115f01e89 100644 --- a/src/agent/border_agent.hpp +++ b/src/agent/border_agent.hpp @@ -36,7 +36,9 @@ #include +#include "agent/instance_params.hpp" #include "agent/ncp.hpp" +#include "backbone_router/backbone_agent.hpp" #include "mdns/mdns.hpp" namespace otbr { @@ -134,6 +136,9 @@ class BorderAgent Mdns::Publisher *mPublisher; Ncp::Controller *mNcp; +#if OTBR_ENABLE_BACKBONE_ROUTER + BackboneRouter::BackboneAgent mBackboneAgent; +#endif uint8_t mExtPanId[kSizeExtPanId]; bool mExtPanIdInitialized; diff --git a/src/agent/instance_params.cpp b/src/agent/instance_params.cpp new file mode 100644 index 00000000000..776193b6fd6 --- /dev/null +++ b/src/agent/instance_params.cpp @@ -0,0 +1,45 @@ +/* + * 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 + * The file implements the agent instance parameters. + */ + +#include "agent/instance_params.hpp" + +namespace otbr { + +InstanceParams &InstanceParams::Get(void) +{ + static InstanceParams sInstanceParams; + + return sInstanceParams; +} + +} // namespace otbr diff --git a/src/agent/instance_params.hpp b/src/agent/instance_params.hpp new file mode 100644 index 00000000000..1cc25afe4b3 --- /dev/null +++ b/src/agent/instance_params.hpp @@ -0,0 +1,105 @@ +/* + * 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 definition for Thread border router agent instance parameters. + */ + +#ifndef OTBR_AGENT_INSATNCE_PARAMS_HPP_ +#define OTBR_AGENT_INSATNCE_PARAMS_HPP_ + +namespace otbr { + +/** + * This class represents the agent instance parameters. + * + */ +class InstanceParams +{ +public: + /** + * This method gets the single `InstanceParams` instance. + * + * @returns The single `InstanceParams` instance. + * + */ + static InstanceParams &Get(void); + + /** + * This method sets the Thread network interface name. + * + * @param[in] aName The Thread network interface name. + * + */ + void SetThreadIfName(const char *aName) { mThreadIfName = aName; } + + /** + * This method gets the Thread network interface name. + * + * @returns The Thread network interface name. + * + */ + const char *GetThreadIfName(void) const { return mThreadIfName; } + +#if OTBR_ENABLE_BACKBONE_ROUTER + /** + * This method sets the Backbone network interface name. + * + * @param[in] aName The Backbone network interface name. + * + */ + void SetBackboneIfName(const char *aName) { mBackboneIfName = aName; } + + /** + * This method gets the Backbone network interface name. + * + * @returns The Backbone network interface name. + * + */ + const char *GetBackboneIfName(void) const { return mBackboneIfName; } +#endif + +private: + InstanceParams() + : mThreadIfName(nullptr) +#if OTBR_ENABLE_BACKBONE_ROUTER + , mBackboneIfName(nullptr) +#endif + { + } + + const char *mThreadIfName; +#if OTBR_ENABLE_BACKBONE_ROUTER + const char *mBackboneIfName; +#endif +}; + +} // namespace otbr + +#endif // OTBR_AGENT_INSATNCE_PARAMS_HPP_ diff --git a/src/agent/main.cpp b/src/agent/main.cpp index a60c28d7904..2e8c571df16 100644 --- a/src/agent/main.cpp +++ b/src/agent/main.cpp @@ -219,7 +219,7 @@ int main(int argc, char *argv[]) int opt; int ret = EXIT_SUCCESS; const char * interfaceName = kDefaultInterfaceName; - const char * backboneInterfaceName = nullptr; + const char * backboneInterfaceName = ""; otbr::Ncp::Controller *ncp = nullptr; bool verbose = false; bool printRadioVersion = false; @@ -282,12 +282,18 @@ int main(int argc, char *argv[]) VerifyOrExit(ncp != nullptr, ret = EXIT_FAILURE); otbrLog(OTBR_LOG_INFO, "Thread interface %s", interfaceName); - otbrLog(OTBR_LOG_INFO, "Backbone interface %s", - backboneInterfaceName == nullptr ? "(null)" : backboneInterfaceName); +#if OTBR_ENABLE_BACKBONE_ROUTER + otbrLog(OTBR_LOG_INFO, "Backbone interface %s", backboneInterfaceName); +#endif { otbr::AgentInstance instance(ncp); + otbr::InstanceParams::Get().SetThreadIfName(interfaceName); +#if OTBR_ENABLE_BACKBONE_ROUTER + otbr::InstanceParams::Get().SetBackboneIfName(backboneInterfaceName); +#endif + SuccessOrExit(ret = instance.Init()); if (printRadioVersion) diff --git a/src/agent/ncp.hpp b/src/agent/ncp.hpp index ddb8bda1c56..8dbd1b9d1ef 100644 --- a/src/agent/ncp.hpp +++ b/src/agent/ncp.hpp @@ -62,12 +62,14 @@ namespace Ncp { */ enum { - kEventExtPanId, ///< Extended PAN ID arrived. - kEventNetworkName, ///< Network name arrived. - kEventPSKc, ///< PSKc arrived. - kEventThreadState, ///< Thread State. - kEventThreadVersion, ///< Thread Version. - kEventUdpForwardStream, ///< UDP forward stream arrived. + kEventExtPanId, ///< Extended PAN ID arrived. + kEventNetworkName, ///< Network name arrived. + kEventPSKc, ///< PSKc arrived. + kEventThreadState, ///< Thread State. + kEventThreadVersion, ///< Thread Version. + kEventUdpForwardStream, ///< UDP forward stream arrived. + kEventBackboneRouterState, ///< Backbone Router State. + kEventBackboneRouterMulticastListenerEvent, ///< Backbone Router Multicast Listener event arrived. }; /** diff --git a/src/agent/ncp_openthread.cpp b/src/agent/ncp_openthread.cpp index 446cd0c6d9a..cd8837b5845 100644 --- a/src/agent/ncp_openthread.cpp +++ b/src/agent/ncp_openthread.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -122,6 +123,11 @@ otbrError ControllerOpenThread::Init(void) VerifyOrExit(result == OT_ERROR_NONE, error = OTBR_ERROR_OPENTHREAD); } +#if OTBR_ENABLE_BACKBONE_ROUTER + otBackboneRouterSetMulticastListenerCallback( + mInstance, &ControllerOpenThread::HandleBackboneRouterMulticastListenerEvent, this); +#endif + mThreadHelper = std::unique_ptr(new otbr::agent::ThreadHelper(mInstance, this)); exit: @@ -166,6 +172,13 @@ void ControllerOpenThread::HandleStateChanged(otChangedFlags aFlags) EventEmitter::Emit(kEventThreadState, attached); } +#if OTBR_ENABLE_BACKBONE_ROUTER + if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE) + { + EventEmitter::Emit(kEventBackboneRouterState); + } +#endif + mThreadHelper->StateChangedCallback(aFlags); } @@ -306,6 +319,21 @@ void ControllerOpenThread::RegisterResetHandler(std::function aHandl mResetHandlers.emplace_back(std::move(aHandler)); } +#if OTBR_ENABLE_BACKBONE_ROUTER +void ControllerOpenThread::HandleBackboneRouterMulticastListenerEvent(void * aContext, + otBackboneRouterMulticastListenerEvent aEvent, + const otIp6Address * aAddress) +{ + static_cast(aContext)->HandleBackboneRouterMulticastListenerEvent(aEvent, aAddress); +} + +void ControllerOpenThread::HandleBackboneRouterMulticastListenerEvent(otBackboneRouterMulticastListenerEvent aEvent, + const otIp6Address * aAddress) +{ + EventEmitter::Emit(kEventBackboneRouterMulticastListenerEvent, aEvent, aAddress); +} +#endif + Controller *Controller::Create(const char *aInterfaceName, const char *aRadioUrl, const char *aBackboneInterfaceName) { return new ControllerOpenThread(aInterfaceName, aRadioUrl, aBackboneInterfaceName); diff --git a/src/agent/ncp_openthread.hpp b/src/agent/ncp_openthread.hpp index f72e06089dd..9e7817ee77a 100644 --- a/src/agent/ncp_openthread.hpp +++ b/src/agent/ncp_openthread.hpp @@ -37,6 +37,7 @@ #include #include +#include #include #include @@ -155,6 +156,12 @@ class ControllerOpenThread : public Controller } void HandleStateChanged(otChangedFlags aFlags); + static void HandleBackboneRouterMulticastListenerEvent(void * aContext, + otBackboneRouterMulticastListenerEvent aEvent, + const otIp6Address * aAddress); + void HandleBackboneRouterMulticastListenerEvent(otBackboneRouterMulticastListenerEvent aEvent, + const otIp6Address * aAddress); + otInstance *mInstance; otPlatformConfig mConfig; diff --git a/src/backbone_router/CMakeLists.txt b/src/backbone_router/CMakeLists.txt new file mode 100644 index 00000000000..7614ccd7fe9 --- /dev/null +++ b/src/backbone_router/CMakeLists.txt @@ -0,0 +1,37 @@ +# +# 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. +# + +add_library(otbr-backbone-router + backbone_agent.cpp + smcroute_manager.cpp +) + +target_link_libraries(otbr-backbone-router PRIVATE + otbr-common + otbr-utils +) diff --git a/src/backbone_router/backbone_agent.cpp b/src/backbone_router/backbone_agent.cpp new file mode 100644 index 00000000000..da269e8d60b --- /dev/null +++ b/src/backbone_router/backbone_agent.cpp @@ -0,0 +1,161 @@ +/* + * 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 + * The file implements the Thread Backbone agent. + */ + +#include "backbone_router/backbone_agent.hpp" + +#include +#include + +#include "common/code_utils.hpp" + +namespace otbr { +namespace BackboneRouter { + +BackboneAgent::BackboneAgent(otbr::Ncp::ControllerOpenThread &aNcp) + : mNcp(aNcp) + , mBackboneRouterState(OT_BACKBONE_ROUTER_STATE_DISABLED) +{ +} + +void BackboneAgent::Init(void) +{ + mNcp.On(Ncp::kEventBackboneRouterState, HandleBackboneRouterState, this); + mNcp.On(Ncp::kEventBackboneRouterMulticastListenerEvent, HandleBackboneRouterMulticastListenerEvent, this); + + mSMCRouteManager.Init(); + + HandleBackboneRouterState(); +} + +void BackboneAgent::HandleBackboneRouterState(void *aContext, int aEvent, va_list aArguments) +{ + OT_UNUSED_VARIABLE(aEvent); + OT_UNUSED_VARIABLE(aArguments); + + assert(aEvent == Ncp::kEventBackboneRouterState); + + static_cast(aContext)->HandleBackboneRouterState(); +} + +void BackboneAgent::HandleBackboneRouterState(void) +{ + otBackboneRouterState state = otBackboneRouterGetState(mNcp.GetInstance()); + bool wasPrimary = (mBackboneRouterState == OT_BACKBONE_ROUTER_STATE_PRIMARY); + + otbrLog(OTBR_LOG_DEBUG, "BackboneAgent: HandleBackboneRouterState: state=%d, mBackboneRouterState=%d", state, + mBackboneRouterState); + VerifyOrExit(mBackboneRouterState != state); + + mBackboneRouterState = state; + + if (IsPrimary()) + { + OnBecomePrimary(); + } + else if (wasPrimary) + { + OnResignPrimary(); + } + +exit: + return; +} + +void BackboneAgent::HandleBackboneRouterMulticastListenerEvent(void *aContext, int aEvent, va_list aArguments) +{ + OT_UNUSED_VARIABLE(aEvent); + + otBackboneRouterMulticastListenerEvent event; + const otIp6Address * address; + + assert(aEvent == Ncp::kEventBackboneRouterMulticastListenerEvent); + + event = static_cast(va_arg(aArguments, int)); + address = va_arg(aArguments, const otIp6Address *); + static_cast(aContext)->HandleBackboneRouterMulticastListenerEvent(event, *address); +} + +void BackboneAgent::HandleBackboneRouterMulticastListenerEvent(otBackboneRouterMulticastListenerEvent aEvent, + const otIp6Address & aAddress) +{ + otbrLog(OTBR_LOG_INFO, "BackboneAgent: Multicast Listener event: %d, address: %s, state: %s", aEvent, + Ip6Address(aAddress).ToString().c_str(), StateToString(mBackboneRouterState)); + + switch (aEvent) + { + case OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ADDED: + mSMCRouteManager.Add(Ip6Address(aAddress)); + break; + case OT_BACKBONE_ROUTER_MULTICAST_LISTENER_REMOVED: + mSMCRouteManager.Remove(Ip6Address(aAddress)); + break; + } +} + +void BackboneAgent::OnBecomePrimary(void) +{ + otbrLog(OTBR_LOG_NOTICE, "BackboneAgent: Backbone Router becomes Primary!"); + + mSMCRouteManager.Enable(); +} + +void BackboneAgent::OnResignPrimary(void) +{ + otbrLog(OTBR_LOG_NOTICE, "BackboneAgent: Backbone Router resigns Primary to %s!", + StateToString(mBackboneRouterState)); + + mSMCRouteManager.Disable(); +} + +const char *BackboneAgent::StateToString(otBackboneRouterState aState) +{ + const char *ret = "Unknown"; + + switch (aState) + { + case OT_BACKBONE_ROUTER_STATE_DISABLED: + ret = "Disabled"; + break; + case OT_BACKBONE_ROUTER_STATE_SECONDARY: + ret = "Secondary"; + break; + case OT_BACKBONE_ROUTER_STATE_PRIMARY: + ret = "Primary"; + break; + } + + return ret; +} + +} // namespace BackboneRouter +} // namespace otbr diff --git a/src/backbone_router/backbone_agent.hpp b/src/backbone_router/backbone_agent.hpp new file mode 100644 index 00000000000..1d8cd9a5390 --- /dev/null +++ b/src/backbone_router/backbone_agent.hpp @@ -0,0 +1,99 @@ +/* + * 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 definition for Thread Backbone agent. + */ + +#ifndef BACKBONE_ROUTER_BACKBONE_AGENT_HPP_ +#define BACKBONE_ROUTER_BACKBONE_AGENT_HPP_ + +#include + +#include "agent/instance_params.hpp" +#include "agent/ncp_openthread.hpp" +#include "backbone_router/smcroute_manager.hpp" + +namespace otbr { +namespace BackboneRouter { + +/** + * @addtogroup border-router-backbone + * + * @brief + * This module includes definition for Thread Backbone agent. + * + * @{ + */ + +/** + * This class implements Thread Backbone agent functionality. + * + */ +class BackboneAgent +{ +public: + /** + * This constructor intiializes the `BackboneAgent` instance. + * + * @param[in] aNcp The Thread instance. + * + */ + BackboneAgent(otbr::Ncp::ControllerOpenThread &aNcp); + + /** + * This method initializes the Backbone agent. + * + */ + void Init(void); + +private: + void OnBecomePrimary(void); + void OnResignPrimary(void); + bool IsPrimary(void) const { return mBackboneRouterState == OT_BACKBONE_ROUTER_STATE_PRIMARY; } + static void HandleBackboneRouterState(void *aContext, int aEvent, va_list aArguments); + void HandleBackboneRouterState(void); + static void HandleBackboneRouterMulticastListenerEvent(void *aContext, int aEvent, va_list aArguments); + void HandleBackboneRouterMulticastListenerEvent(otBackboneRouterMulticastListenerEvent aEvent, + const otIp6Address & aAddress); + static const char *StateToString(otBackboneRouterState aState); + + otbr::Ncp::ControllerOpenThread &mNcp; + otBackboneRouterState mBackboneRouterState; + SMCRouteManager mSMCRouteManager; +}; + +#endif // OTBR_ENABLE_BACKBONE_ROUTER + +/** + * @} + */ + +} // namespace BackboneRouter +} // namespace otbr diff --git a/src/backbone_router/smcroute_manager.cpp b/src/backbone_router/smcroute_manager.cpp new file mode 100644 index 00000000000..f2a774ab3d5 --- /dev/null +++ b/src/backbone_router/smcroute_manager.cpp @@ -0,0 +1,192 @@ +/* + * 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 + * The file implements the SMCRoute manager. + */ + +#include "backbone_router/smcroute_manager.hpp" + +#include +#include + +#include + +#include "common/code_utils.hpp" +#include "utils/system_utils.hpp" + +namespace otbr { + +namespace BackboneRouter { + +void SMCRouteManager::Init(void) +{ + assert(!mEnabled); + + StartSMCRouteService(); +} + +void SMCRouteManager::Enable(void) +{ + otbrError error = OTBR_ERROR_NONE; + + VerifyOrExit(!mEnabled); + + mEnabled = true; + + Flush(); + + // Add mroute rules: 65520 (0xfff0) allow outbound for MA scope >= admin (4) + SuccessOrExit(error = AllowOutboundMulticast()); + + // Add mroute rules for the current Multicast Listeners Table + for (const Ip6Address &address : mListenerSet) + { + SuccessOrExit(error = AddRoute(address)); + } + +exit: + otbrLogResult(error, "SMCRouteManager: %s", __FUNCTION__); +} + +void SMCRouteManager::Disable(void) +{ + otbrError error = OTBR_ERROR_NONE; + + VerifyOrExit(mEnabled); + + mEnabled = false; + + Flush(); + + // Remove mroute rules for the current Multicast Listeners Table + for (const Ip6Address &address : mListenerSet) + { + SuccessOrExit(error = DeleteRoute(address)); + } + + // Remove mroute rules: forbid outbound Multicast traffic + SuccessOrExit(error = ForbidOutboundMulticast()); + +exit: + otbrLogResult(error, "SMCRouteManager: %s", __FUNCTION__); +} + +void SMCRouteManager::StartSMCRouteService(void) +{ + otbrError error = OTBR_ERROR_NONE; + std::chrono::system_clock::time_point deadline; + + VerifyOrExit(SystemUtils::ExecuteCommand("smcroutectl kill || true") == 0, error = OTBR_ERROR_SMCROUTE); + VerifyOrExit(SystemUtils::ExecuteCommand("smcrouted") == 0, error = OTBR_ERROR_SMCROUTE); + + deadline = std::chrono::system_clock::now() + std::chrono::seconds(10); + + while (std::chrono::system_clock::now() < deadline) + { + usleep(10000); + + VerifyOrExit((error = Flush()) != OTBR_ERROR_NONE); + } + +exit: + SuccessOrDie(error, "Failed to start SMCRoute service"); +} + +void SMCRouteManager::Add(const Ip6Address &aAddress) +{ + otbrError error = OTBR_ERROR_NONE; + + assert(mListenerSet.find(aAddress) == mListenerSet.end()); + mListenerSet.insert(aAddress); + + VerifyOrExit(mEnabled); + + Flush(); + error = AddRoute(aAddress); + +exit: + otbrLogResult(error, "SMCRouteManager: AddRoute %s", aAddress.ToString().c_str()); +} + +void SMCRouteManager::Remove(const Ip6Address &aAddress) +{ + otbrError error = OTBR_ERROR_NONE; + + assert(mListenerSet.find(aAddress) != mListenerSet.end()); + mListenerSet.erase(aAddress); + + VerifyOrExit(mEnabled); + + Flush(); + error = DeleteRoute(aAddress); +exit: + otbrLogResult(error, "SMCRouteManager: RemoveRoute %s", aAddress.ToString().c_str()); +} + +otbrError SMCRouteManager::AllowOutboundMulticast(void) +{ + return SystemUtils::ExecuteCommand("smcroutectl add %s :: :: 65520 %s", InstanceParams::Get().GetThreadIfName(), + InstanceParams::Get().GetBackboneIfName()) == 0 + ? OTBR_ERROR_NONE + : OTBR_ERROR_SMCROUTE; +} + +otbrError SMCRouteManager::ForbidOutboundMulticast(void) +{ + return SystemUtils::ExecuteCommand("smcroutectl remove %s :: :: 65520 %s", InstanceParams::Get().GetThreadIfName(), + InstanceParams::Get().GetBackboneIfName()) == 0 + ? OTBR_ERROR_NONE + : OTBR_ERROR_SMCROUTE; +} + +otbrError SMCRouteManager::AddRoute(const Ip6Address &aAddress) +{ + return SystemUtils::ExecuteCommand("smcroutectl add %s :: %s %s", InstanceParams::Get().GetBackboneIfName(), + aAddress.ToString().c_str(), InstanceParams::Get().GetThreadIfName()) == 0 + ? OTBR_ERROR_NONE + : OTBR_ERROR_SMCROUTE; +} + +otbrError SMCRouteManager::DeleteRoute(const Ip6Address &aAddress) +{ + return SystemUtils::ExecuteCommand("smcroutectl del %s :: %s %s", InstanceParams::Get().GetBackboneIfName(), + aAddress.ToString().c_str(), InstanceParams::Get().GetThreadIfName()) == 0 + ? OTBR_ERROR_NONE + : OTBR_ERROR_SMCROUTE; +} + +otbrError SMCRouteManager::Flush(void) +{ + return SystemUtils::ExecuteCommand("smcroutectl flush") == 0 ? OTBR_ERROR_NONE : OTBR_ERROR_SMCROUTE; +} + +} // namespace BackboneRouter + +} // namespace otbr diff --git a/src/backbone_router/smcroute_manager.hpp b/src/backbone_router/smcroute_manager.hpp new file mode 100644 index 00000000000..0d6bb119e7b --- /dev/null +++ b/src/backbone_router/smcroute_manager.hpp @@ -0,0 +1,127 @@ +/* + * 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 definition for SMCRoute manager. + */ + +#ifndef BACKBONE_ROUTER_SMCROUTE_MANAGER_HPP_ +#define BACKBONE_ROUTER_SMCROUTE_MANAGER_HPP_ + +#include +#include + +#include "agent/instance_params.hpp" +#include "agent/ncp_openthread.hpp" +#include "utils/system_utils.hpp" + +namespace otbr { +namespace BackboneRouter { + +/** + * @addtogroup border-router-backbone + * + * @brief + * This module includes definition for SMCRoute manager. + * + * @{ + */ + +/** + * This class implements SMCRoute manager functionality. + * + */ +class SMCRouteManager +{ +public: + /** + * This constructor initializes a SMCRoute manager instance. + * + */ + explicit SMCRouteManager() + : mEnabled(false) + { + } + + /** + * This method initializes a SMCRoute manager instance. + * + */ + void Init(void); + + /** + * This method enables the SMCRoute manager. + * + */ + void Enable(void); + + /** + * This method disables the SMCRoute manager. + * + */ + void Disable(void); + + /** + * This method adds a multicast route. + * + * NOTE: Multicast routes are only effective when the SMCRoute manager is enabled. + * + * @param[in] aAddress The multicast address. + * + */ + void Add(const Ip6Address &aAddress); + + /** + * This method removes a multicast route. + * + * @param[in] aAddress The multicast address. + * + */ + void Remove(const Ip6Address &aAddress); + +private: + void StartSMCRouteService(void); + otbrError Flush(void); + otbrError ForbidOutboundMulticast(void); + otbrError AllowOutboundMulticast(void); + otbrError AddRoute(const Ip6Address &aAddress); + otbrError DeleteRoute(const Ip6Address &aAddress); + + std::set mListenerSet; + bool mEnabled : 1; +}; + +/** + * @} + */ + +} // namespace BackboneRouter +} // namespace otbr + +#endif // BACKBONE_ROUTER_SMCROUTE_MANAGER_HPP_ diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 3408c147efa..9b9072d411d 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -28,8 +28,11 @@ add_library(otbr-common logging.cpp + types.cpp ) target_link_libraries(otbr-common PUBLIC otbr-config + openthread-ftd + openthread-posix ) diff --git a/src/common/code_utils.hpp b/src/common/code_utils.hpp index e374d55a668..c8a8eaf83f3 100644 --- a/src/common/code_utils.hpp +++ b/src/common/code_utils.hpp @@ -65,6 +65,24 @@ } \ } while (false) +/** + * This macro verifies a given error status to be successful (compared against value zero (0)), otherwise, it emits a + * given error messages and exits the program. + * + * @param[in] aStatus A scalar error status to be evaluated against zero (0). + * @param[in] aMessage A message (text string) to print on failure. + * + */ +#define SuccessOrDie(aStatus, aMessage) \ + do \ + { \ + if ((aStatus) != 0) \ + { \ + otbrLog(OTBR_LOG_EMERG, "FAILED %s:%d - %s", __FUNCTION__, __LINE__, aMessage); \ + exit(-1); \ + } \ + } while (false) + /** * This checks for the specified condition, which is expected to * commonly be true, and both executes @a ... and branches to the @@ -85,6 +103,24 @@ } \ } while (false) +/** + * This macro checks for the specified condition, which is expected to commonly be true, + * and both prints the message and terminates the program if the condition is false. + * + * @param[in] aCondition The condition to verify + * @param[in] aMessage A message (text string) to print on failure. + * + */ +#define VerifyOrDie(aCondition, aMessage) \ + do \ + { \ + if (!(aCondition)) \ + { \ + otbrLog(OTBR_LOG_EMERG, "FAILED %s:%d - %s", __FUNCTION__, __LINE__, aMessage); \ + exit(-1); \ + } \ + } while (false) + /** * This unconditionally executes @a ... and branches to the local * label 'exit'. diff --git a/src/common/logging.cpp b/src/common/logging.cpp index bf1e8a1a1de..062028c9d22 100644 --- a/src/common/logging.cpp +++ b/src/common/logging.cpp @@ -163,11 +163,6 @@ const char *otbrErrorString(otbrError aError) return error; } -void otbrLogResult(const char *aAction, otbrError aError) -{ - otbrLog((aError == OTBR_ERROR_NONE ? OTBR_LOG_INFO : OTBR_LOG_WARNING), "%s: %s", aAction, otbrErrorString(aError)); -} - void otbrLogDeinit(void) { closelog(); diff --git a/src/common/logging.hpp b/src/common/logging.hpp index d65887b2429..cee374442d0 100644 --- a/src/common/logging.hpp +++ b/src/common/logging.hpp @@ -85,16 +85,22 @@ void otbrLogInit(const char *aIdent, int aLevel, bool aPrintStderr); void otbrLog(int aLevel, const char *aFormat, ...); /** - * This function log a action result according to @p aError. + * This macro log a action result according to @p aError. * * If @p aError is OTBR_ERROR_NONE, the log level will be OTBR_LOG_INFO, * otherwise OTBR_LOG_WARNING. * - * @param[in] aAction The action description. * @param[in] aError The action result. + * @param[in] aFormat Format string as in printf. * */ -void otbrLogResult(const char *aAction, otbrError aError); +#define otbrLogResult(aError, aFormat, ...) \ + do \ + { \ + otbrError _err = (aError); \ + otbrLog(_err == OTBR_ERROR_NONE ? OTBR_LOG_INFO : OTBR_LOG_WARNING, aFormat ": %s", ##__VA_ARGS__, \ + otbrErrorString(_err)); \ + } while (0) /** * This function log at level @p aLevel. diff --git a/src/common/types.cpp b/src/common/types.cpp new file mode 100644 index 00000000000..4a40b747100 --- /dev/null +++ b/src/common/types.cpp @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#include +#include + +#include "common/code_utils.hpp" +#include "common/logging.hpp" +#include "common/types.hpp" + +namespace otbr { + +Ip6Address::Ip6Address(const otIp6Address &aAddress) +{ + static_assert(sizeof(*this) == sizeof(aAddress), "wrong Ip6Address size"); + + m32[0] = aAddress.mFields.m32[0]; + m32[1] = aAddress.mFields.m32[1]; + m32[2] = aAddress.mFields.m32[2]; + m32[3] = aAddress.mFields.m32[3]; +} + +std::string Ip6Address::ToString() const +{ + char strbuf[INET6_ADDRSTRLEN]; + + VerifyOrDie(inet_ntop(AF_INET6, this->m8, strbuf, sizeof(strbuf)) != nullptr, + "Failed to convert Ip6 address to string"); + + return std::string(strbuf); +} + +} // namespace otbr diff --git a/src/common/types.hpp b/src/common/types.hpp index 99987cad7bc..33f653e27e8 100644 --- a/src/common/types.hpp +++ b/src/common/types.hpp @@ -37,9 +37,12 @@ #include "openthread-br/config.h" #include +#include #include #include +#include + #ifndef IN6ADDR_ANY /** * Any IPv6 address literal. @@ -64,7 +67,8 @@ enum otbrError OTBR_ERROR_DBUS = -2, ///< DBus error. OTBR_ERROR_MDNS = -3, ///< MDNS error. OTBR_ERROR_OPENTHREAD = -4, ///< OpenThread error. - OTBR_ERROR_REST = -5 ///< Rest Server error. + OTBR_ERROR_REST = -5, ///< Rest Server error. + OTBR_ERROR_SMCROUTE = -6, ///< SMCRoute error. }; namespace otbr { @@ -109,6 +113,24 @@ class Ip6Address m8[15] = aLocator & 0xff; } + /** + * Constructor with an Thread Ip6 address. + * + * @param[in] aAddress The Thread Ip6 address. + * + */ + Ip6Address(const otIp6Address &aAddress); + + /** + * This method overloads `<` operator and compares if the Ip6 address is smaller than the other address. + * + * @param[in] aOther The other Ip6 address to compare with. + * + * @returns Whether the Ip6 address is smaller than the other address. + * + */ + bool operator<(const Ip6Address &aOther) const { return memcmp(this, &aOther, sizeof(Ip6Address)) < 0; } + /** * Retrieve the 16-bit Thread locator. * @@ -117,6 +139,14 @@ class Ip6Address */ uint16_t ToLocator(void) const { return static_cast(m8[14] << 8 | m8[15]); } + /** + * This method returns the string representation for the Ip6 address. + * + * @returns The string representation of the Ip6 address. + * + */ + std::string ToString() const; + union { uint8_t m8[16]; diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index fb47f28c9ab..e76f0466088 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -33,6 +33,7 @@ add_library(otbr-utils pskc.cpp steering_data.cpp strcpy_utils.cpp + system_utils.cpp ) target_link_libraries(otbr-utils PRIVATE otbr-common diff --git a/src/utils/system_utils.cpp b/src/utils/system_utils.cpp new file mode 100644 index 00000000000..9a935c03edb --- /dev/null +++ b/src/utils/system_utils.cpp @@ -0,0 +1,67 @@ +/* + * 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 + * The file implements POSIX system utilities. + */ + +#include "system_utils.hpp" + +#include +#include +#include + +#include "common/logging.hpp" + +namespace otbr { +namespace SystemUtils { + +enum +{ + kSystemCommandMaxLength = 1024, ///< Max length of a system call command. +}; + +int ExecuteCommand(const char *aFormat, ...) +{ + char cmd[kSystemCommandMaxLength]; + int exitCode; + va_list args; + + va_start(args, aFormat); + vsnprintf(cmd, sizeof(cmd), aFormat, args); + va_end(args); + + exitCode = system(cmd); + + otbrLog(exitCode == 0 ? OTBR_LOG_INFO : OTBR_LOG_WARNING, "$?=%-3d: %s", exitCode, cmd); + return exitCode; +} + +} // namespace SystemUtils +} // namespace otbr diff --git a/src/utils/system_utils.hpp b/src/utils/system_utils.hpp new file mode 100644 index 00000000000..4ae2dad1597 --- /dev/null +++ b/src/utils/system_utils.hpp @@ -0,0 +1,62 @@ +/* + * 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 POSIX system utilities. + */ + +#ifndef OTBR_UTILS_SYSTEM_UTILS_HPP_ +#define OTBR_UTILS_SYSTEM_UTILS_HPP_ + +namespace otbr { +namespace SystemUtils { + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This method formats a system command to execute. + * + * @param[in] aFormat A pointer to the format string. + * @param[in] ... Arguments for the format specification. + * + * @returns The command exit code. + * + */ +int ExecuteCommand(const char *aFormat, ...); + +#ifdef __cplusplus +} +#endif + +} // namespace SystemUtils +} // namespace otbr + +#endif // OTBR_UTILS_SYSTEM_UTILS_HPP_ diff --git a/tests/mdns/CMakeLists.txt b/tests/mdns/CMakeLists.txt index 108014a0995..a602a7545dd 100644 --- a/tests/mdns/CMakeLists.txt +++ b/tests/mdns/CMakeLists.txt @@ -33,6 +33,7 @@ add_executable(otbr-test-mdns target_link_libraries(otbr-test-mdns PRIVATE otbr-config otbr-mdns + openthread-ftd ) add_test( diff --git a/third_party/openthread/repo b/third_party/openthread/repo index 7a24666bf45..8707b638942 160000 --- a/third_party/openthread/repo +++ b/third_party/openthread/repo @@ -1 +1 @@ -Subproject commit 7a24666bf45b92f2a2bedd0559411c7ce019832c +Subproject commit 8707b638942fa396fe0c3c11a918f79082aadb8e