[backbone-router] implement DUA policy routing (#586)

diff --git a/script/_rt_tables b/script/_rt_tables
new file mode 100644
index 0000000..ef1437d
--- /dev/null
+++ b/script/_rt_tables
@@ -0,0 +1,47 @@
+#!/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 router tables.
+#
+
+rt_tables_uninstall()
+{
+    with BACKBONE_ROUTER || return 0
+
+    sudo sed -i.bak '/88\s\+openthread/d' /etc/iproute2/rt_tables
+}
+
+rt_tables_install()
+{
+    with BACKBONE_ROUTER || return 0
+
+    rt_tables_uninstall
+
+    sudo sh -c 'echo "88 openthread" >>/etc/iproute2/rt_tables'
+}
diff --git a/script/setup b/script/setup
index 390c0ed..6c61f63 100755
--- a/script/setup
+++ b/script/setup
@@ -39,6 +39,7 @@
 . script/_dns64
 . script/_dhcpv6_pd
 . script/_network_manager
+. script/_rt_tables
 . script/_swapfile
 . script/_sudo_extend
 . script/_disable_services
@@ -55,9 +56,11 @@
     dhcpv6_pd_uninstall
     nat64_uninstall
     dns64_uninstall
+    rt_tables_uninstall
     ipforward_uninstall
 
     ipforward_install
+    rt_tables_install
     nat64_install
     dns64_install
     network_manager_install
diff --git a/src/backbone_router/CMakeLists.txt b/src/backbone_router/CMakeLists.txt
index 48d0c04..e4c7361 100644
--- a/src/backbone_router/CMakeLists.txt
+++ b/src/backbone_router/CMakeLists.txt
@@ -28,6 +28,7 @@
 
 add_library(otbr-backbone-router
     backbone_agent.cpp
+    dua_routing_manager.cpp
     nd_proxy.cpp
 )
 
diff --git a/src/backbone_router/backbone_agent.cpp b/src/backbone_router/backbone_agent.cpp
index f4cffd7..b8d3981 100644
--- a/src/backbone_router/backbone_agent.cpp
+++ b/src/backbone_router/backbone_agent.cpp
@@ -104,6 +104,7 @@
 #if OTBR_ENABLE_DUA_ROUTING
     if (mDomainPrefix.IsValid())
     {
+        mDuaRoutingManager.Enable(mDomainPrefix);
         mNdProxyManager.Enable(mDomainPrefix);
     }
 #endif
@@ -115,6 +116,7 @@
             StateToString(mBackboneRouterState));
 
 #if OTBR_ENABLE_DUA_ROUTING
+    mDuaRoutingManager.Disable();
     mNdProxyManager.Disable();
 #endif
 }
@@ -181,7 +183,10 @@
     VerifyOrExit(IsPrimary() && aEvent != OT_BACKBONE_ROUTER_DOMAIN_PREFIX_REMOVED);
 
 #if OTBR_ENABLE_DUA_ROUTING
+    mDuaRoutingManager.Disable();
     mNdProxyManager.Disable();
+
+    mDuaRoutingManager.Enable(mDomainPrefix);
     mNdProxyManager.Enable(mDomainPrefix);
 #endif
 
diff --git a/src/backbone_router/backbone_agent.hpp b/src/backbone_router/backbone_agent.hpp
index 06ebb34..2c1cdbc 100644
--- a/src/backbone_router/backbone_agent.hpp
+++ b/src/backbone_router/backbone_agent.hpp
@@ -38,6 +38,7 @@
 
 #include "agent/instance_params.hpp"
 #include "agent/ncp_openthread.hpp"
+#include "backbone_router/dua_routing_manager.hpp"
 #include "backbone_router/nd_proxy.hpp"
 #include "common/mainloop.hpp"
 
@@ -115,9 +116,9 @@
     otbr::Ncp::ControllerOpenThread &mNcp;
     otBackboneRouterState            mBackboneRouterState;
     Ip6Prefix                        mDomainPrefix;
-
 #if OTBR_ENABLE_DUA_ROUTING
-    NdProxyManager mNdProxyManager;
+    NdProxyManager    mNdProxyManager;
+    DuaRoutingManager mDuaRoutingManager;
 #endif
 };
 
diff --git a/src/backbone_router/dua_routing_manager.cpp b/src/backbone_router/dua_routing_manager.cpp
new file mode 100644
index 0000000..3b024fe
--- /dev/null
+++ b/src/backbone_router/dua_routing_manager.cpp
@@ -0,0 +1,100 @@
+/*
+ *    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 DUA routing functionalities.
+ */
+
+#include "backbone_router/dua_routing_manager.hpp"
+
+#if OTBR_ENABLE_DUA_ROUTING
+
+#include "common/code_utils.hpp"
+
+namespace otbr {
+
+namespace BackboneRouter {
+
+void DuaRoutingManager::Enable(const Ip6Prefix &aDomainPrefix)
+{
+    VerifyOrExit(!mEnabled);
+    mEnabled = true;
+
+    mDomainPrefix = aDomainPrefix;
+
+    AddDefaultRouteToThread();
+    AddPolicyRouteToBackbone();
+
+exit:
+    otbrLogResult(OTBR_ERROR_NONE, "DuaRoutingManager: %s", __FUNCTION__);
+}
+
+void DuaRoutingManager::Disable(void)
+{
+    VerifyOrExit(mEnabled);
+    mEnabled = false;
+
+    DelDefaultRouteToThread();
+    DelPolicyRouteToBackbone();
+
+exit:
+    otbrLogResult(OTBR_ERROR_NONE, "DuaRoutingManager: %s", __FUNCTION__);
+}
+
+void DuaRoutingManager::AddDefaultRouteToThread(void)
+{
+    SystemUtils::ExecuteCommand("ip -6 route add %s dev %s proto static metric 1", mDomainPrefix.ToString().c_str(),
+                                InstanceParams::Get().GetThreadIfName());
+}
+
+void DuaRoutingManager::DelDefaultRouteToThread(void)
+{
+    SystemUtils::ExecuteCommand("ip -6 route del %s dev %s proto static metric 1", mDomainPrefix.ToString().c_str(),
+                                InstanceParams::Get().GetThreadIfName());
+}
+
+void DuaRoutingManager::AddPolicyRouteToBackbone(void)
+{
+    // Packets from Thread interface use route table "openthread"
+    SystemUtils::ExecuteCommand("ip -6 rule add iif %s table openthread", InstanceParams::Get().GetThreadIfName());
+    SystemUtils::ExecuteCommand("ip -6 route add %s dev %s proto static table openthread",
+                                mDomainPrefix.ToString().c_str(), InstanceParams::Get().GetBackboneIfName());
+}
+
+void DuaRoutingManager::DelPolicyRouteToBackbone(void)
+{
+    SystemUtils::ExecuteCommand("ip -6 rule del iif %s table openthread", InstanceParams::Get().GetThreadIfName());
+    SystemUtils::ExecuteCommand("ip -6 route del %s dev %s proto static table openthread",
+                                mDomainPrefix.ToString().c_str(), InstanceParams::Get().GetBackboneIfName());
+}
+
+} // namespace BackboneRouter
+} // namespace otbr
+
+#endif // OTBR_ENABLE_DUA_ROUTING
diff --git a/src/backbone_router/dua_routing_manager.hpp b/src/backbone_router/dua_routing_manager.hpp
new file mode 100644
index 0000000..6af9dec
--- /dev/null
+++ b/src/backbone_router/dua_routing_manager.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 DUA routing functionalities.
+ */
+
+#ifndef BACKBONE_ROUTER_DUA_ROUTING_MANAGER
+#define BACKBONE_ROUTER_DUA_ROUTING_MANAGER
+
+#if OTBR_ENABLE_DUA_ROUTING
+
+#include <set>
+#include <openthread/backbone_router_ftd.h>
+
+#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 DUA routing functionalities.
+ *
+ * @{
+ */
+
+/**
+ * This class implements the DUA routing manager.
+ *
+ */
+class DuaRoutingManager
+{
+public:
+    /**
+     * This constructor initializes a DUA routing manager instance.
+     *
+     */
+    explicit DuaRoutingManager()
+        : mEnabled(false)
+    {
+    }
+
+    /**
+     * This method enables the DUA routing manager.
+     *
+     */
+    void Enable(const Ip6Prefix &aDomainPrefix);
+
+    /**
+     * This method disables the DUA routing manager.
+     *
+     */
+    void Disable(void);
+
+private:
+    void AddDefaultRouteToThread(void);
+    void DelDefaultRouteToThread(void);
+    void AddPolicyRouteToBackbone(void);
+    void DelPolicyRouteToBackbone(void);
+
+    Ip6Prefix mDomainPrefix;
+    bool      mEnabled : 1;
+};
+
+/**
+ * @}
+ */
+
+} // namespace BackboneRouter
+} // namespace otbr
+
+#endif // OTBR_ENABLE_DUA_ROUTING
+
+#endif // BACKBONE_ROUTER_DUA_ROUTING_MANAGER
diff --git a/third_party/openthread/repo b/third_party/openthread/repo
index b775146..5bc74b7 160000
--- a/third_party/openthread/repo
+++ b/third_party/openthread/repo
@@ -1 +1 @@
-Subproject commit b7751460e04a233589393fd4faccef5bc6e8e88b
+Subproject commit 5bc74b71132e5327114d07ae9438475db481ea32