From 1b3922edcd0c254b39d57d91b9e027069cd8c82f Mon Sep 17 00:00:00 2001
From: chengzrz <czrzrichard@gmail.com>
Date: Mon, 22 Nov 2021 15:34:04 +0800
Subject: [PATCH 03/14] Modified the procedure of running a pod to adapt to
 kata 2.0

Signed-off-by: chengzrz <czrzrichard@gmail.com>
---
 src/common/constants.h                        |   2 +
 src/daemon/entry/cri/cni_network_plugin.cc    |  33 ++++-
 src/daemon/entry/cri/cri_constants.cc         |   1 +
 src/daemon/entry/cri/cri_constants.h          |   1 +
 src/daemon/entry/cri/cri_helpers.cc           |   1 +
 src/daemon/entry/cri/cri_helpers.h            |   1 +
 .../cri_pod_sandbox_manager_service_impl.cc   | 128 +++++++++++-----
 .../cri_pod_sandbox_manager_service_impl.h    |   2 +-
 src/daemon/entry/cri/cri_security_context.cc  |   3 +
 .../executor/container_cb/execution_create.c  |  65 +++++++++
 .../executor/container_cb/execution_network.c |   3 +-
 .../executor/container_cb/execution_network.h |   1 -
 .../modules/api/network_namespace_api.h       |  35 +++++
 src/daemon/modules/api/specs_api.h            |   4 +-
 src/daemon/modules/container/container_unix.c |   1 +
 .../modules/service/inspect_container.c       |  35 +++++
 .../modules/service/network_namespace_api.c   |  80 ++++++++++
 .../modules/service/service_container.c       |  15 +-
 src/daemon/modules/spec/specs.c               |  64 ++++++--
 src/daemon/modules/spec/specs_namespace.c     |  86 ++++++++++-
 src/daemon/modules/spec/specs_namespace.h     |   5 +
 src/utils/cutils/namespace.h                  |  18 +++
 src/utils/cutils/utils_file.c                 |  23 +++
 src/utils/cutils/utils_file.h                 |   2 +
 src/utils/cutils/utils_network.c              | 138 ++++++++++++++++++
 src/utils/cutils/utils_network.h              |  33 +++++
 26 files changed, 713 insertions(+), 67 deletions(-)
 create mode 100644 src/daemon/modules/api/network_namespace_api.h
 create mode 100644 src/daemon/modules/service/network_namespace_api.c
 create mode 100644 src/utils/cutils/utils_network.c
 create mode 100644 src/utils/cutils/utils_network.h

diff --git a/src/common/constants.h b/src/common/constants.h
index 94640fa5..cb6ce189 100644
--- a/src/common/constants.h
+++ b/src/common/constants.h
@@ -129,6 +129,8 @@ extern "C" {
 #define EVENT_ARGS_MAX 255
 #define EVENT_EXTRA_ANNOTATION_MAX 255
 
+#define NETNS_LEN 16
+
 /* container id max length */
 #define CONTAINER_ID_MAX_LEN 64
 
diff --git a/src/daemon/entry/cri/cni_network_plugin.cc b/src/daemon/entry/cri/cni_network_plugin.cc
index 35273c3e..ffdbeb10 100644
--- a/src/daemon/entry/cri/cni_network_plugin.cc
+++ b/src/daemon/entry/cri/cni_network_plugin.cc
@@ -28,6 +28,7 @@
 #include "utils.h"
 #include "errors.h"
 #include "service_container_api.h"
+#include "network_namespace_api.h"
 
 namespace Network {
 static auto GetLoNetwork(std::vector<std::string> binDirs) -> std::unique_ptr<CNINetwork>
@@ -486,9 +487,15 @@ void CniNetworkPlugin::SetUpPod(const std::string &ns, const std::string &name,
     if (err.NotEmpty()) {
         return;
     }
-    std::string netnsPath = GetNetNS(id, err);
-    if (err.NotEmpty()) {
-        ERROR("CNI failed to retrieve network namespace path: %s", err.GetCMessage());
+
+    auto iter = annotations.find(CRIHelpers::Constants::POD_SANDBOX_KEY);
+    if (iter == annotations.end()) {
+        ERROR("Failed to find sandbox key from annotations");
+        return;
+    }
+    const std::string netnsPath = iter->second;
+    if (netnsPath.length() == 0) {
+        ERROR("Failed to get network namespace path");
         return;
     }
 
@@ -517,7 +524,6 @@ void CniNetworkPlugin::SetUpPod(const std::string &ns, const std::string &name,
             err.AppendError(tmpErr.GetMessage());
         }
     }
-
     UnlockNetworkMap(err);
 }
 
@@ -593,10 +599,21 @@ void CniNetworkPlugin::TearDownPod(const std::string &ns, const std::string &nam
     }
     Errors tmpErr;
 
-    std::string netnsPath = GetNetNS(id, err);
-    if (err.NotEmpty()) {
-        WARN("CNI failed to retrieve network namespace path: %s", err.GetCMessage());
-        err.Clear();
+    auto iter = annotations.find(CRIHelpers::Constants::POD_SANDBOX_KEY);
+    if (iter == annotations.end()) {
+        ERROR("Failed to find sandbox key from annotations");
+        return;
+    }
+    std::string netnsPath = iter->second;
+    if (netnsPath.length() == 0) {
+        ERROR("Failed to get network namespace path");
+        return;
+    }
+
+    // When netns file does not exist, netnsPath is assigned to an
+    // empty string so that lxc can handle the path properly
+    if (!util_file_exists(netnsPath.c_str())) {
+        netnsPath = "";
     }
 
     RLockNetworkMap(err);
diff --git a/src/daemon/entry/cri/cri_constants.cc b/src/daemon/entry/cri/cri_constants.cc
index b557d56a..265e38e5 100644
--- a/src/daemon/entry/cri/cri_constants.cc
+++ b/src/daemon/entry/cri/cri_constants.cc
@@ -16,6 +16,7 @@
 
 namespace CRI {
 const std::string Constants::namespaceModeHost { "host" };
+const std::string Constants::namespaceModeFile { "file" };
 const std::string Constants::nameDelimiter { "_" };
 const std::string Constants::kubePrefix { "k8s" };
 const std::string Constants::sandboxContainerName { "POD" };
diff --git a/src/daemon/entry/cri/cri_constants.h b/src/daemon/entry/cri/cri_constants.h
index 4e964714..95b82660 100644
--- a/src/daemon/entry/cri/cri_constants.h
+++ b/src/daemon/entry/cri/cri_constants.h
@@ -20,6 +20,7 @@ namespace CRI {
 class Constants {
 public:
     const static std::string namespaceModeHost;
+    const static std::string namespaceModeFile;
     // sandboxname default values
     const static std::string nameDelimiter;
     constexpr static char nameDelimiterChar { '_' };
diff --git a/src/daemon/entry/cri/cri_helpers.cc b/src/daemon/entry/cri/cri_helpers.cc
index f45c669f..525d65a0 100644
--- a/src/daemon/entry/cri/cri_helpers.cc
+++ b/src/daemon/entry/cri/cri_helpers.cc
@@ -42,6 +42,7 @@ const std::string Constants::CONTAINER_TYPE_LABEL_CONTAINER { "container" };
 const std::string Constants::CONTAINER_LOGPATH_LABEL_KEY { "cri.container.logpath" };
 const std::string Constants::CONTAINER_HUGETLB_ANNOTATION_KEY { "cri.container.hugetlblimit" };
 const std::string Constants::SANDBOX_ID_LABEL_KEY { "cri.sandbox.id" };
+const std::string Constants::POD_SANDBOX_KEY { "sandboxkey" };
 const std::string Constants::KUBERNETES_CONTAINER_NAME_LABEL { "io.kubernetes.container.name" };
 const std::string Constants::POD_INFRA_CONTAINER_NAME { "POD" };
 const std::string Constants::DOCKER_IMAGEID_PREFIX { "docker://" };
diff --git a/src/daemon/entry/cri/cri_helpers.h b/src/daemon/entry/cri/cri_helpers.h
index 9eccc1da..5c2f6517 100644
--- a/src/daemon/entry/cri/cri_helpers.h
+++ b/src/daemon/entry/cri/cri_helpers.h
@@ -39,6 +39,7 @@ public:
     static const std::string CONTAINER_LOGPATH_LABEL_KEY;
     static const std::string CONTAINER_HUGETLB_ANNOTATION_KEY;
     static const std::string SANDBOX_ID_LABEL_KEY;
+    static const std::string POD_SANDBOX_KEY;
     static const std::string KUBERNETES_CONTAINER_NAME_LABEL;
     static const std::string POD_INFRA_CONTAINER_NAME;
     // DOCKER_IMAGEID_PREFIX is the prefix of image id in container status.
diff --git a/src/daemon/entry/cri/cri_pod_sandbox_manager_service_impl.cc b/src/daemon/entry/cri/cri_pod_sandbox_manager_service_impl.cc
index 0f9ef044..eb1cd09f 100644
--- a/src/daemon/entry/cri/cri_pod_sandbox_manager_service_impl.cc
+++ b/src/daemon/entry/cri/cri_pod_sandbox_manager_service_impl.cc
@@ -13,6 +13,8 @@
  * Description: provide cri pod sandbox manager service implementation
  *********************************************************************************/
 #include "cri_pod_sandbox_manager_service_impl.h"
+
+#include <sys/mount.h>
 #include "isula_libutils/log.h"
 #include "isula_libutils/host_config.h"
 #include "isula_libutils/container_config.h"
@@ -24,7 +26,11 @@
 #include "naming.h"
 #include "service_container_api.h"
 #include "cxxutils.h"
+#include "network_namespace_api.h"
 #include "cri_image_manager_service_impl.h"
+#include "utils_network.h"
+#include "namespace.h"
+#include "constants.h"
 
 namespace CRI {
 auto PodSandboxManagerServiceImpl::EnsureSandboxImageExists(const std::string &image, Errors &error) -> bool
@@ -49,7 +55,8 @@ auto PodSandboxManagerServiceImpl::EnsureSandboxImageExists(const std::string &i
 }
 
 void PodSandboxManagerServiceImpl::ApplySandboxLinuxOptions(const runtime::v1alpha2::LinuxPodSandboxConfig &lc,
-                                                            host_config *hc, container_config *custom_config, Errors &error)
+                                                            host_config *hc, container_config *custom_config,
+                                                            Errors &error)
 {
     CRISecurity::ApplySandboxSecurityContext(lc, custom_config, hc, error);
     if (error.NotEmpty()) {
@@ -279,8 +286,8 @@ error_out:
 }
 
 container_create_request *PodSandboxManagerServiceImpl::GenerateSandboxCreateContainerRequest(
-    const runtime::v1alpha2::PodSandboxConfig &config, const std::string &image,
-    std::string &jsonCheckpoint, const std::string &runtimeHandler, Errors &error)
+    const runtime::v1alpha2::PodSandboxConfig &config, const std::string &image, std::string &jsonCheckpoint,
+    const std::string &runtimeHandler, Errors &error)
 {
     container_create_request *create_request = nullptr;
     host_config *hostconfig = nullptr;
@@ -338,7 +345,8 @@ cleanup:
 
 auto PodSandboxManagerServiceImpl::CreateSandboxContainer(const runtime::v1alpha2::PodSandboxConfig &config,
                                                           const std::string &image, std::string &jsonCheckpoint,
-                                                          const std::string &runtimeHandler, Errors &error) -> std::string
+                                                          const std::string &runtimeHandler, Errors &error)
+-> std::string
 {
     std::string response_id;
     container_create_request *create_request =
@@ -464,16 +472,12 @@ cleanup:
 }
 
 void PodSandboxManagerServiceImpl::SetupSandboxNetwork(const runtime::v1alpha2::PodSandboxConfig &config,
-                                                       const std::string &response_id, const std::string &jsonCheckpoint,
-                                                       Errors &error)
+                                                       const std::string &response_id,
+                                                       const std::string &jsonCheckpoint, const container_inspect *inspect_data, Errors &error)
 {
     std::map<std::string, std::string> stdAnnos;
     std::map<std::string, std::string> networkOptions;
-
-    container_inspect *inspect_data = CRIHelpers::InspectContainer(response_id, error, false);
-    if (error.NotEmpty()) {
-        return;
-    }
+    const char* sandbox_key = get_sandbox_key(inspect_data);
 
     // Setup sandbox files
     if (config.has_dns_config() && inspect_data->resolv_conf_path != nullptr) {
@@ -493,7 +497,10 @@ void PodSandboxManagerServiceImpl::SetupSandboxNetwork(const runtime::v1alpha2::
     CRIHelpers::ProtobufAnnoMapToStd(config.annotations(), stdAnnos);
     stdAnnos[CRIHelpers::Constants::POD_CHECKPOINT_KEY] = jsonCheckpoint;
     networkOptions["UID"] = config.metadata().uid();
-
+    if (sandbox_key == NULL) {
+        goto cleanup;
+    }
+    stdAnnos.insert(std::pair<std::string, std::string>(CRIHelpers::Constants::POD_SANDBOX_KEY, sandbox_key));
     m_pluginManager->SetUpPod(config.metadata().namespace_(), config.metadata().name(),
                               Network::DEFAULT_NETWORK_INTERFACE_NAME, response_id, stdAnnos, networkOptions, error);
     if (error.NotEmpty()) {
@@ -503,15 +510,16 @@ void PodSandboxManagerServiceImpl::SetupSandboxNetwork(const runtime::v1alpha2::
     }
 
 cleanup:
-    free_container_inspect(inspect_data);
+    return;
 }
 
-
 auto PodSandboxManagerServiceImpl::RunPodSandbox(const runtime::v1alpha2::PodSandboxConfig &config,
                                                  const std::string &runtimeHandler, Errors &error) -> std::string
 {
     std::string response_id;
     std::string jsonCheckpoint;
+    container_inspect *inspect_data = nullptr;
+    char *netnsPath = nullptr;
 
     if (m_cb == nullptr || m_cb->container.create == nullptr || m_cb->container.start == nullptr) {
         error.SetError("Unimplemented callback");
@@ -539,13 +547,33 @@ auto PodSandboxManagerServiceImpl::RunPodSandbox(const runtime::v1alpha2::PodSan
         error.Clear();
     }
 
-    // Step 4: Start the sandbox container.
-    StartSandboxContainer(response_id, error);
+    // Step 4: mount network namespace when network mode is file
+    inspect_data = CRIHelpers::InspectContainer(response_id, error, true);
     if (error.NotEmpty()) {
         goto cleanup;
     }
+    if (inspect_data == nullptr || inspect_data->host_config == nullptr) {
+        error.Errorf("Failed to retrieve inspect data");
+        ERROR("Failed to retrieve inspect data");
+        goto cleanup;
+    }
+    netnsPath = get_sandbox_key(inspect_data);
+    if (namespace_is_file(inspect_data->host_config->network_mode)) {
+        if (!util_file_exists(netnsPath) || util_mount_namespace(netnsPath) != 0) {
+            error.Errorf("Failed to mount network namespace");
+            ERROR("Failed to mount network namespace");
+            goto cleanup;
+        }
+    }
+
     // Step 5: Setup networking for the sandbox.
-    SetupSandboxNetwork(config, response_id, jsonCheckpoint, error);
+    SetupSandboxNetwork(config, response_id, jsonCheckpoint, inspect_data, error);
+    if (error.NotEmpty()) {
+        goto cleanup;
+    }
+
+    // Step 6: Start the sandbox container.
+    StartSandboxContainer(response_id, error);
     if (error.NotEmpty()) {
         goto cleanup;
     }
@@ -555,13 +583,21 @@ cleanup:
         SetNetworkReady(response_id, true, error);
         DEBUG("set %s ready", response_id.c_str());
         error.Clear();
+    } else {
+        if (netnsPath != nullptr && remove_network_namespace(netnsPath) != 0) {
+            ERROR("Failed to remove network namespace");
+        }
     }
+    free_container_inspect(inspect_data);
+    free(netnsPath);
     return response_id;
 }
 
 auto PodSandboxManagerServiceImpl::GetRealSandboxIDToStop(const std::string &podSandboxID, bool &hostNetwork,
-                                                          std::string &name, std::string &ns, std::string &realSandboxID,
-                                                          std::map<std::string, std::string> &stdAnnos, Errors &error) -> int
+                                                          std::string &name, std::string &ns,
+                                                          std::string &realSandboxID,
+                                                          std::map<std::string, std::string> &stdAnnos, Errors &error)
+-> int
 {
     Errors statusErr;
 
@@ -670,16 +706,32 @@ auto PodSandboxManagerServiceImpl::GetNetworkReady(const std::string &podSandbox
 }
 
 auto PodSandboxManagerServiceImpl::ClearCniNetwork(const std::string &realSandboxID, bool hostNetwork,
-                                                   const std::string &ns,
-                                                   const std::string &name, std::vector<std::string> &errlist,
+                                                   const std::string &ns, const std::string &name,
+                                                   std::vector<std::string> &errlist,
                                                    std::map<std::string, std::string> &stdAnnos, Errors &
                                                    /*error*/) -> int
 {
     Errors networkErr;
+    container_inspect* inspect_data = nullptr;
 
     bool ready = GetNetworkReady(realSandboxID, networkErr);
     if (!hostNetwork && (ready || networkErr.NotEmpty())) {
         Errors pluginErr;
+
+        // hostNetwork has indicated network mode which render host config unnecessary
+        // so that with_host_config is set to be false.
+        inspect_data = CRIHelpers::InspectContainer(realSandboxID, pluginErr, false);
+        if (pluginErr.NotEmpty()) {
+            ERROR("Failed to inspect container");
+        }
+
+        char* netnsPath = get_sandbox_key(inspect_data);
+        if (netnsPath == nullptr) {
+            ERROR("Failed to get network namespace path");
+            return 0;
+        }
+
+        stdAnnos.insert(std::pair<std::string, std::string>(CRIHelpers::Constants::POD_SANDBOX_KEY, netnsPath));
         m_pluginManager->TearDownPod(ns, name, Network::DEFAULT_NETWORK_INTERFACE_NAME, realSandboxID, stdAnnos,
                                      pluginErr);
         if (pluginErr.NotEmpty()) {
@@ -691,8 +743,13 @@ auto PodSandboxManagerServiceImpl::ClearCniNetwork(const std::string &realSandbo
             if (pluginErr.NotEmpty()) {
                 WARN("set network ready: %s", pluginErr.GetCMessage());
             }
+            // umount netns when cni removed network successfully
+            if (util_umount_namespace(netnsPath) != 0) {
+                ERROR("Failed to umount directory %s:%s", netnsPath, strerror(errno));
+            }
         }
     }
+    free_container_inspect(inspect_data);
     return 0;
 }
 
@@ -806,7 +863,6 @@ void PodSandboxManagerServiceImpl::ClearNetworkReady(const std::string &podSandb
     }
 }
 
-
 int PodSandboxManagerServiceImpl::DoRemovePodSandbox(const std::string &realSandboxID, std::vector<std::string> &errors)
 {
     int ret = 0;
@@ -878,8 +934,8 @@ cleanup:
     error.SetAggregate(errors);
 }
 
-auto PodSandboxManagerServiceImpl::SharesHostNetwork(const container_inspect *inspect) ->
-runtime::v1alpha2::NamespaceMode
+auto PodSandboxManagerServiceImpl::SharesHostNetwork(const container_inspect *inspect)
+-> runtime::v1alpha2::NamespaceMode
 {
     if (inspect != nullptr && inspect->host_config != nullptr && (inspect->host_config->network_mode != nullptr) &&
         std::string(inspect->host_config->network_mode) == CRI::Constants::namespaceModeHost) {
@@ -1032,10 +1088,9 @@ void PodSandboxManagerServiceImpl::GetIPs(const std::string &podSandboxID, const
     error.Clear();
 }
 
-void PodSandboxManagerServiceImpl::SetSandboxStatusNetwork(const container_inspect *inspect,
-                                                           const std::string &podSandboxID,
-                                                           std::unique_ptr<runtime::v1alpha2::PodSandboxStatus> &podStatus,
-                                                           Errors &error)
+void PodSandboxManagerServiceImpl::SetSandboxStatusNetwork(
+    const container_inspect *inspect, const std::string &podSandboxID,
+    std::unique_ptr<runtime::v1alpha2::PodSandboxStatus> &podStatus, Errors &error)
 {
     std::vector<std::string> ips;
     size_t i;
@@ -1052,10 +1107,9 @@ void PodSandboxManagerServiceImpl::SetSandboxStatusNetwork(const container_inspe
     }
 }
 
-void PodSandboxManagerServiceImpl::PodSandboxStatusToGRPC(const container_inspect *inspect,
-                                                          const std::string &podSandboxID,
-                                                          std::unique_ptr<runtime::v1alpha2::PodSandboxStatus> &podStatus,
-                                                          Errors &error)
+void PodSandboxManagerServiceImpl::PodSandboxStatusToGRPC(
+    const container_inspect *inspect, const std::string &podSandboxID,
+    std::unique_ptr<runtime::v1alpha2::PodSandboxStatus> &podStatus, Errors &error)
 {
     int64_t createdAt {};
     runtime::v1alpha2::NamespaceOption *options { nullptr };
@@ -1129,8 +1183,8 @@ PodSandboxManagerServiceImpl::PodSandboxStatus(const std::string &podSandboxID,
 }
 
 void PodSandboxManagerServiceImpl::ListPodSandboxFromGRPC(const runtime::v1alpha2::PodSandboxFilter *filter,
-                                                          container_list_request **request, bool *filterOutReadySandboxes,
-                                                          Errors &error)
+                                                          container_list_request **request,
+                                                          bool *filterOutReadySandboxes, Errors &error)
 {
     *request = (container_list_request *)util_common_calloc_s(sizeof(container_list_request));
     if (*request == nullptr) {
@@ -1175,9 +1229,9 @@ void PodSandboxManagerServiceImpl::ListPodSandboxFromGRPC(const runtime::v1alpha
     }
 }
 
-void PodSandboxManagerServiceImpl::ListPodSandboxToGRPC(container_list_response *response,
-                                                        std::vector<std::unique_ptr<runtime::v1alpha2::PodSandbox>> *pods,
-                                                        bool filterOutReadySandboxes, Errors &error)
+void PodSandboxManagerServiceImpl::ListPodSandboxToGRPC(
+    container_list_response *response, std::vector<std::unique_ptr<runtime::v1alpha2::PodSandbox>> *pods,
+    bool filterOutReadySandboxes, Errors &error)
 {
     for (size_t i = 0; i < response->containers_len; i++) {
         std::unique_ptr<runtime::v1alpha2::PodSandbox> pod(new runtime::v1alpha2::PodSandbox);
diff --git a/src/daemon/entry/cri/cri_pod_sandbox_manager_service_impl.h b/src/daemon/entry/cri/cri_pod_sandbox_manager_service_impl.h
index fa5d153c..34907fa6 100644
--- a/src/daemon/entry/cri/cri_pod_sandbox_manager_service_impl.h
+++ b/src/daemon/entry/cri/cri_pod_sandbox_manager_service_impl.h
@@ -82,7 +82,7 @@ private:
     void SetNetworkReady(const std::string &podSandboxID, bool ready, Errors &error);
     void StartSandboxContainer(const std::string &response_id, Errors &error);
     void SetupSandboxNetwork(const runtime::v1alpha2::PodSandboxConfig &config, const std::string &response_id,
-                             const std::string &jsonCheckpoint, Errors &error);
+                             const std::string &jsonCheckpoint, const container_inspect *inspect_data, Errors &error);
     void SetupSandboxFiles(const std::string &resolvPath, const runtime::v1alpha2::PodSandboxConfig &config,
                            Errors &error);
     void StopContainerHelper(const std::string &containerID, Errors &error);
diff --git a/src/daemon/entry/cri/cri_security_context.cc b/src/daemon/entry/cri/cri_security_context.cc
index b6a5fcdc..3ff8a0cb 100644
--- a/src/daemon/entry/cri/cri_security_context.cc
+++ b/src/daemon/entry/cri/cri_security_context.cc
@@ -169,6 +169,9 @@ static void ModifyHostNetworkOptionForSandbox(const runtime::v1alpha2::Namespace
         hostConfig->network_mode = util_strdup_s(CRI::Constants::namespaceModeHost.c_str());
         free(hostConfig->uts_mode);
         hostConfig->uts_mode = util_strdup_s(CRI::Constants::namespaceModeHost.c_str());
+    } else {
+        free(hostConfig->network_mode);
+        hostConfig->network_mode = util_strdup_s(CRI::Constants::namespaceModeFile.c_str());
     }
     // Note: default networkMode is not supported
 }
diff --git a/src/daemon/executor/container_cb/execution_create.c b/src/daemon/executor/container_cb/execution_create.c
index 05c0fd78..95a7d9ab 100644
--- a/src/daemon/executor/container_cb/execution_create.c
+++ b/src/daemon/executor/container_cb/execution_create.c
@@ -46,6 +46,7 @@
 #include "utils.h"
 #include "error.h"
 #include "constants.h"
+#include "namespace.h"
 #include "events_sender_api.h"
 #include "sysinfo.h"
 #include "service_container_api.h"
@@ -58,6 +59,7 @@
 #include "utils_verify.h"
 #include "selinux_label.h"
 #include "opt_log.h"
+#include "network_namespace_api.h"
 
 static int do_init_cpurt_cgroups_path(const char *path, int recursive_depth, const char *mnt_root,
                                       int64_t cpu_rt_period, int64_t cpu_rt_runtime);
@@ -1395,6 +1397,63 @@ out:
     return res;
 }
 
+static char *new_pod_sandbox_key(void)
+{
+    int nret = 0;
+    char random[NETNS_LEN + 1] = { 0x00 };
+    char netns[PATH_MAX] = { 0x00 };
+    const char *netns_fmt = "/var/run/netns/isulacni-%s";
+
+    nret = util_generate_random_str(random, NETNS_LEN);
+    if (nret != 0) {
+        ERROR("Failed to generate random netns");
+        return NULL;
+    }
+
+    nret = snprintf(netns, sizeof(netns), netns_fmt, random);
+    if (nret < 0 || (size_t)nret >= sizeof(netns)) {
+        ERROR("snprintf netns failed");
+        return NULL;
+    }
+
+    return util_strdup_s(netns);
+}
+
+static int generate_network_settings(const host_config *host_config, container_config_v2_common_config *v2_spec)
+{
+    container_config_v2_common_config_network_settings *settings = NULL;
+
+    if (!namespace_is_file(host_config->network_mode)) {
+        return 0;
+    }
+
+    settings = (container_config_v2_common_config_network_settings *)util_common_calloc_s(sizeof(
+                                                                                              container_config_v2_common_config_network_settings));
+    if (settings == NULL) {
+        ERROR("Out of memory");
+        return -1;
+    }
+
+    settings->sandbox_key = new_pod_sandbox_key();
+    if (settings->sandbox_key == NULL) {
+        ERROR("Failed to generate sandbox key");
+        goto err_out;
+    }
+
+    if (prepare_network_namespace(settings->sandbox_key) != 0) {
+        ERROR("Failed to create network namespace");
+        goto err_out;
+    }
+
+    v2_spec->network_settings = settings;
+
+    return 0;
+
+err_out:
+    free_container_config_v2_common_config_network_settings(settings);
+    return -1;
+}
+
 static int cpurt_controller_init(const char *cgroups_path)
 {
     int ret = 0;
@@ -1568,6 +1627,12 @@ int container_create_cb(const container_create_request *request, container_creat
         goto umount_shm;
     }
 
+    if (generate_network_settings(host_spec, v2_spec) != 0) {
+        ERROR("Failed to generate network settings");
+        cc = ISULAD_ERR_EXEC;
+        goto umount_shm;
+    }
+
     if (merge_config_for_syscontainer(request, host_spec, v2_spec->config, oci_spec) != 0) {
         ERROR("Failed to merge config for syscontainer");
         cc = ISULAD_ERR_EXEC;
diff --git a/src/daemon/executor/container_cb/execution_network.c b/src/daemon/executor/container_cb/execution_network.c
index 2c662bc1..5532e3fc 100644
--- a/src/daemon/executor/container_cb/execution_network.c
+++ b/src/daemon/executor/container_cb/execution_network.c
@@ -34,6 +34,7 @@
 #include "err_msg.h"
 #include "utils_file.h"
 #include "utils_string.h"
+#include "network_namespace_api.h"
 
 static int write_hostname_to_file(const char *rootfs, const char *hostname)
 {
@@ -1038,4 +1039,4 @@ int init_container_network_confs(const char *id, const char *rootpath, const hos
 
 out:
     return ret;
-}
+}
\ No newline at end of file
diff --git a/src/daemon/executor/container_cb/execution_network.h b/src/daemon/executor/container_cb/execution_network.h
index dee56fed..b6428b05 100644
--- a/src/daemon/executor/container_cb/execution_network.h
+++ b/src/daemon/executor/container_cb/execution_network.h
@@ -29,7 +29,6 @@ extern "C" {
 int merge_network(const host_config *host_spec, const char *rootfs, const char *runtime_root,
                   const char *id, const char *hostname);
 
-
 int init_container_network_confs(const char *id, const char *rootpath, const host_config *hc,
                                  container_config_v2_common_config *common_config);
 
diff --git a/src/daemon/modules/api/network_namespace_api.h b/src/daemon/modules/api/network_namespace_api.h
new file mode 100644
index 00000000..9a18b1c0
--- /dev/null
+++ b/src/daemon/modules/api/network_namespace_api.h
@@ -0,0 +1,35 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *     http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: chengzeruizhi
+ * Create: 2021-10-19
+ * Description: set up CRI network namespace
+ *********************************************************************************/
+
+#ifndef DAEMON_MODULES_API_NETWORK_NAMESPACE_API
+#define DAEMON_MODULES_API_NETWORK_NAMESPACE_API
+
+#include <stdbool.h>
+
+#include "container_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int prepare_network_namespace(const char *netns_path);
+int remove_network_namespace(const char *netns);
+char *get_sandbox_key(const container_inspect *inspect_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // DAEMON_MODULES_API_NETWORK_NAMESPACE_API
diff --git a/src/daemon/modules/api/specs_api.h b/src/daemon/modules/api/specs_api.h
index 6c4db007..c4ad79aa 100644
--- a/src/daemon/modules/api/specs_api.h
+++ b/src/daemon/modules/api/specs_api.h
@@ -37,7 +37,9 @@ int save_oci_config(const char *id, const char *rootpath, const oci_runtime_spec
 int parse_security_opt(const host_config *host_spec, bool *no_new_privileges, char ***label_opts,
                        size_t *label_opts_len, char **seccomp_profile);
 
-int merge_share_namespace(oci_runtime_spec *oci_spec, const host_config *host_spec);
+int merge_share_namespace(oci_runtime_spec *oci_spec, const host_config *host_spec,
+                          const container_config_v2_common_config_network_settings *network_settings);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/daemon/modules/container/container_unix.c b/src/daemon/modules/container/container_unix.c
index 1904161e..98f91ea9 100644
--- a/src/daemon/modules/container/container_unix.c
+++ b/src/daemon/modules/container/container_unix.c
@@ -45,6 +45,7 @@
 #include "utils_file.h"
 #include "utils_string.h"
 #include "volume_api.h"
+#include "namespace.h"
 
 static int parse_container_log_configs(container_t *cont);
 
diff --git a/src/daemon/modules/service/inspect_container.c b/src/daemon/modules/service/inspect_container.c
index d678f7bb..b060fe12 100644
--- a/src/daemon/modules/service/inspect_container.c
+++ b/src/daemon/modules/service/inspect_container.c
@@ -31,6 +31,7 @@
 #include "container_api.h"
 #include "isulad_config.h"
 #include "err_msg.h"
+#include "namespace.h"
 
 static int dup_path_and_args(const container_t *cont, char **path, char ***args, size_t *args_len)
 {
@@ -458,6 +459,36 @@ out:
     return ret;
 }
 
+static int pack_inspect_network_settings(const container_t *cont, container_inspect *inspect)
+{
+    if (cont == NULL || cont->common_config == NULL) {
+        ERROR("Failed to get v2 common config from container");
+        return -1;
+    }
+
+    if (!namespace_is_file(cont->hostconfig->network_mode)) {
+        return 0;
+    }
+
+    if (cont->common_config->network_settings == NULL) {
+        ERROR("Failed to get network settings from container");
+        return -1;
+    }
+
+    if (inspect->network_settings == NULL) {
+        inspect->network_settings =
+            (container_inspect_network_settings *)util_common_calloc_s(sizeof(container_inspect_network_settings));
+        if (inspect->network_settings == NULL) {
+            ERROR("Out of memory");
+            return -1;
+        }
+    }
+
+    inspect->network_settings->sandbox_key = util_strdup_s(cont->common_config->network_settings->sandbox_key);
+
+    return 0;
+}
+
 static int merge_default_ulimit_with_ulimit(container_inspect *out_inspect)
 {
     int ret = 0;
@@ -509,6 +540,10 @@ static container_inspect *pack_inspect_data(const container_t *cont, bool with_h
         ERROR("Failed to pack inspect general data, continue to pack other information");
     }
 
+    if (pack_inspect_network_settings(cont, inspect) != 0) {
+        ERROR("Failed to pack inspect network settings, continue to pack other information");
+    }
+
     if (pack_inspect_container_state(cont, inspect) != 0) {
         ERROR("Failed to pack inspect state data, continue to pack other information");
     }
diff --git a/src/daemon/modules/service/network_namespace_api.c b/src/daemon/modules/service/network_namespace_api.c
new file mode 100644
index 00000000..e28e6f74
--- /dev/null
+++ b/src/daemon/modules/service/network_namespace_api.c
@@ -0,0 +1,80 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *     http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: chengzeruizhi
+ * Create: 2021-10-19
+ * Description: set up CRI network namespace
+ *********************************************************************************/
+#define _GNU_SOURCE
+
+#include "network_namespace_api.h"
+
+#include <sys/mount.h>
+
+#include "utils_network.h"
+
+int prepare_network_namespace(const char *netns_path)
+{
+    if (netns_path == NULL) {
+        ERROR("Invalid netns_path");
+        return -1;
+    }
+
+    if (util_create_netns_file(netns_path) != 0) {
+        ERROR("Failed to prepare network namespace file");
+        return -1;
+    }
+
+    return 0;
+}
+
+int remove_network_namespace(const char *netns_path)
+{
+    int get_err = 0;
+
+    if (netns_path == NULL) {
+        ERROR("Invalid netns_path");
+        return -1;
+    }
+
+    if (!util_file_exists(netns_path)) {
+        WARN("Namespace file does not exist");
+        return 0;
+    }
+
+    if (umount2(netns_path, MNT_DETACH) != 0 && errno != EINVAL) {
+        ERROR("Failed to umount directory %s:%s", netns_path, strerror(errno));
+        return -1;
+    }
+
+    if (!util_force_remove_file(netns_path, &get_err)) {
+        ERROR("Failed to remove file %s, error: %s", netns_path, strerror(get_err));
+        return -1;
+    }
+
+    return 0;
+}
+
+char *get_sandbox_key(const container_inspect *inspect_data)
+{
+    char *sandbox_key = NULL;
+
+    if (inspect_data == NULL) {
+        ERROR("Invalid container");
+        return NULL;
+    }
+    if (inspect_data->network_settings == NULL) {
+        ERROR("Inspect data does not have network settings");
+        return NULL;
+    }
+    sandbox_key = util_strdup_s(inspect_data->network_settings->sandbox_key);
+
+    return sandbox_key;
+}
\ No newline at end of file
diff --git a/src/daemon/modules/service/service_container.c b/src/daemon/modules/service/service_container.c
index 0bcfb0e9..27288f6d 100644
--- a/src/daemon/modules/service/service_container.c
+++ b/src/daemon/modules/service/service_container.c
@@ -59,6 +59,8 @@
 #include "utils_string.h"
 #include "utils_verify.h"
 #include "volume_api.h"
+#include "utils_network.h"
+#include "network_namespace_api.h"
 
 #define KATA_RUNTIME "kata-runtime"
 
@@ -227,7 +229,7 @@ static int renew_oci_config(const container_t *cont, oci_runtime_spec *oci_spec)
         goto out;
     }
 
-    ret = merge_share_namespace(oci_spec, cont->hostconfig);
+    ret = merge_share_namespace(oci_spec, cont->hostconfig, cont->common_config->network_settings);
     if (ret != 0) {
         ERROR("Failed to merge share ns");
         goto out;
@@ -895,6 +897,10 @@ int start_container(container_t *cont, const char *console_fifos[], bool reset_r
     }
 
 set_stopped:
+    if (namespace_is_file(cont->hostconfig->network_mode) &&
+        util_umount_namespace(cont->common_config->network_settings->sandbox_key) != 0) {
+        ERROR("Failed to clean up network namespace");
+    }
     container_state_set_error(cont->state, (const char *)g_isulad_errmsg);
     util_contain_errmsg(g_isulad_errmsg, &exit_code);
     container_state_set_stopped(cont->state, exit_code);
@@ -1085,6 +1091,13 @@ static int do_delete_container(container_t *cont)
         goto out;
     }
 
+    // clean up mounted network namespace
+    if (cont->common_config->network_settings != NULL &&
+        util_file_exists(cont->common_config->network_settings->sandbox_key)
+        && remove_network_namespace(cont->common_config->network_settings->sandbox_key) != 0) {
+        ERROR("Failed to remove network when deleting container %s", cont->common_config->id);
+    }
+
     ret = snprintf(container_state, sizeof(container_state), "%s/%s", statepath, id);
     if (ret < 0 || (size_t)ret >= sizeof(container_state)) {
         ERROR("Failed to sprintf container_state");
diff --git a/src/daemon/modules/spec/specs.c b/src/daemon/modules/spec/specs.c
index d8d05ba0..fc53bd14 100644
--- a/src/daemon/modules/spec/specs.c
+++ b/src/daemon/modules/spec/specs.c
@@ -22,14 +22,14 @@
 #include <isula_libutils/defs.h>
 #include <isula_libutils/json_common.h>
 #include <isula_libutils/oci_runtime_config_linux.h>
+#include <isula_libutils/oci_runtime_spec.h>
+#include <isula_libutils/oci_runtime_hooks.h>
+#include <isula_libutils/host_config.h>
+#include <isula_libutils/log.h>
 #include <limits.h>
 #include <stdint.h>
 
-#include "isula_libutils/log.h"
 #include "specs_api.h"
-#include "isula_libutils/oci_runtime_spec.h"
-#include "isula_libutils/oci_runtime_hooks.h"
-#include "isula_libutils/host_config.h"
 #include "utils.h"
 #include "isulad_config.h"
 #include "namespace.h"
@@ -1377,10 +1377,9 @@ out:
     return ret;
 }
 
-static int merge_share_namespace_helper(const oci_runtime_spec *oci_spec, const char *path, const char *type)
+static int merge_share_namespace_helper(const oci_runtime_spec *oci_spec, const char *ns_path, const char *type)
 {
     int ret = -1;
-    char *ns_path = NULL;
     size_t len = 0;
     size_t org_len = 0;
     size_t i = 0;
@@ -1390,11 +1389,6 @@ static int merge_share_namespace_helper(const oci_runtime_spec *oci_spec, const
     len = oci_spec->linux->namespaces_len;
     work_ns = oci_spec->linux->namespaces;
 
-    ret = get_share_namespace_path(type, path, &ns_path);
-    if (ret != 0) {
-        ERROR("Failed to get share ns type:%s path:%s", type, path);
-        goto out;
-    }
     for (i = 0; i < org_len; i++) {
         if (strcmp(type, work_ns[i]->type) == 0) {
             free(work_ns[i]->path);
@@ -1433,7 +1427,6 @@ static int merge_share_namespace_helper(const oci_runtime_spec *oci_spec, const
     }
     ret = 0;
 out:
-    free(ns_path);
     if (work_ns != NULL) {
         oci_spec->linux->namespaces = work_ns;
         oci_spec->linux->namespaces_len = len;
@@ -1443,14 +1436,55 @@ out:
 
 static int merge_share_single_namespace(const oci_runtime_spec *oci_spec, const char *path, const char *type)
 {
+    int ret = 0;
+    char *ns_path = NULL;
+
     if (path == NULL) {
         return 0;
     }
 
-    return merge_share_namespace_helper(oci_spec, path, type);
+    ret = get_share_namespace_path(type, path, &ns_path);
+    if (ret != 0) {
+        ERROR("Failed to get share ns type:%s path:%s", type, path);
+        return -1;
+    }
+
+    ret = merge_share_namespace_helper(oci_spec, ns_path, type);
+    if (ret != 0) {
+        ERROR("Failed to merge share namespace namespace helper");
+    }
+
+    free(ns_path);
+    return ret;
+}
+
+static int merge_share_network_namespace(oci_runtime_spec *oci_spec, const host_config *host_spec,
+                                         const container_config_v2_common_config_network_settings *network_settings, const char *type)
+{
+    int ret = 0;
+    char *ns_path = NULL;
+
+    if (host_spec->network_mode == NULL) {
+        return 0;
+    }
+
+    ret = get_network_namespace_path(host_spec, network_settings, type, &ns_path);
+    if (ret != 0) {
+        ERROR("Failed to get network namespace path");
+        return -1;
+    }
+
+    ret = merge_share_namespace_helper(oci_spec, ns_path, type);
+    if (ret != 0) {
+        ERROR("Failed to merge share namespace namespace helper");
+    }
+
+    free(ns_path);
+    return ret;
 }
 
-int merge_share_namespace(oci_runtime_spec *oci_spec, const host_config *host_spec)
+int merge_share_namespace(oci_runtime_spec *oci_spec, const host_config *host_spec,
+                          const container_config_v2_common_config_network_settings *network_settings)
 {
     int ret = -1;
 
@@ -1475,7 +1509,7 @@ int merge_share_namespace(oci_runtime_spec *oci_spec, const host_config *host_sp
     }
 
     // network
-    if (merge_share_single_namespace(oci_spec, host_spec->network_mode, TYPE_NAMESPACE_NETWORK) != 0) {
+    if (merge_share_network_namespace(oci_spec, host_spec, network_settings, TYPE_NAMESPACE_NETWORK) != 0) {
         ret = -1;
         goto out;
     }
diff --git a/src/daemon/modules/spec/specs_namespace.c b/src/daemon/modules/spec/specs_namespace.c
index e291f092..eea0b3ff 100644
--- a/src/daemon/modules/spec/specs_namespace.c
+++ b/src/daemon/modules/spec/specs_namespace.c
@@ -17,15 +17,16 @@
 #include <string.h>
 #include <stdlib.h>
 #include <limits.h>
-#include <isula_libutils/container_config_v2.h>
 #include <signal.h>
 #include <stdio.h>
+#include <isula_libutils/log.h>
+#include <isula_libutils/container_config_v2.h>
 
-#include "isula_libutils/log.h"
 #include "utils.h"
 #include "namespace.h"
 #include "container_api.h"
 #include "err_msg.h"
+#include "network_namespace_api.h"
 
 static char *parse_share_namespace_with_prefix(const char *type, const char *path)
 {
@@ -133,3 +134,84 @@ char *get_container_process_label(const char *cid)
 out:
     return result;
 }
+
+typedef int (*namespace_mode_check)(const host_config *host_spec,
+                                    const container_config_v2_common_config_network_settings *network_settings,
+                                    const char *type, char **dest_path);
+
+struct get_netns_path_handler {
+    char *mode;
+    namespace_mode_check handle;
+};
+
+static int handle_get_path_from_none(const host_config *host_spec,
+                                     const container_config_v2_common_config_network_settings *network_settings,
+                                     const char *type, char **dest_path)
+{
+    *dest_path = NULL;
+    return 0;
+}
+
+static int handle_get_path_from_host(const host_config *host_spec,
+                                     const container_config_v2_common_config_network_settings *network_settings,
+                                     const char *type, char **dest_path)
+{
+    *dest_path = namespace_get_host_namespace_path(host_spec->network_mode);
+    if (*dest_path == NULL) {
+        return -1;
+    }
+    return 0;
+}
+
+static int handle_get_path_from_container(const host_config *host_spec,
+                                          const container_config_v2_common_config_network_settings *network_settings, const char *type,
+                                          char **dest_path)
+{
+    *dest_path = parse_share_namespace_with_prefix(type, host_spec->network_mode);
+    if (*dest_path == NULL) {
+        return -1;
+    }
+    return 0;
+}
+
+static int handle_get_path_from_file(const host_config *host_spec,
+                                     const container_config_v2_common_config_network_settings *network_settings,
+                                     const char *type, char **dest_path)
+{
+    if (network_settings == NULL || network_settings->sandbox_key == NULL) {
+        ERROR("Invalid sandbox key for file mode network");
+        return -1;
+    }
+
+    *dest_path = util_strdup_s(network_settings->sandbox_key);
+    return 0;
+}
+
+int get_network_namespace_path(const host_config *host_spec,
+                               const container_config_v2_common_config_network_settings *network_settings,
+                               const char *type, char **dest_path)
+{
+    int index;
+    int ret = -1;
+    struct get_netns_path_handler handler_jump_table[] = {
+        { SHARE_NAMESPACE_NONE, handle_get_path_from_none },
+        { SHARE_NAMESPACE_HOST, handle_get_path_from_host },
+        { SHARE_NAMESPACE_PREFIX, handle_get_path_from_container },
+        { SHARE_NAMESPACE_FILE, handle_get_path_from_file },
+    };
+    size_t jump_table_size = sizeof(handler_jump_table) / sizeof(handler_jump_table[0]);
+    const char *network_mode = host_spec->network_mode;
+
+    if (network_mode == NULL || dest_path == NULL) {
+        return -1;
+    }
+
+    for (index = 0; index < jump_table_size; ++index) {
+        if (strncmp(network_mode, handler_jump_table[index].mode, strlen(handler_jump_table[index].mode)) == 0) {
+            ret = handler_jump_table[index].handle(host_spec, network_settings, type, dest_path);
+            return ret;
+        }
+    }
+
+    return ret;
+}
\ No newline at end of file
diff --git a/src/daemon/modules/spec/specs_namespace.h b/src/daemon/modules/spec/specs_namespace.h
index 526ad4e0..68e41399 100644
--- a/src/daemon/modules/spec/specs_namespace.h
+++ b/src/daemon/modules/spec/specs_namespace.h
@@ -17,6 +17,8 @@
 
 #include <stdbool.h>
 #include <string.h>
+#include <isula_libutils/host_config.h>
+#include <isula_libutils/container_config_v2.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -24,6 +26,9 @@ extern "C" {
 
 int get_share_namespace_path(const char *type, const char *src_path, char **dest_path);
 char *get_container_process_label(const char *path);
+int get_network_namespace_path(const host_config *host_spec,
+                               const container_config_v2_common_config_network_settings *network_settings,
+                               const char *type, char **dest_path);
 
 #ifdef __cplusplus
 }
diff --git a/src/utils/cutils/namespace.h b/src/utils/cutils/namespace.h
index cf768056..26a9bb19 100644
--- a/src/utils/cutils/namespace.h
+++ b/src/utils/cutils/namespace.h
@@ -37,6 +37,8 @@ typedef enum {
 #define SHARE_NAMESPACE_HOST "host"
 #define SHARE_NAMESPACE_NONE "none"
 #define SHARE_NAMESPACE_SHAREABLE "shareable"
+#define SHARE_NAMESPACE_BRIDGE "bridge"
+#define SHARE_NAMESPACE_FILE "file"
 
 #define SHARE_NAMESPACE_PID_HOST_PATH "/proc/1/ns/pid"
 #define SHARE_NAMESPACE_NET_HOST_PATH "/proc/1/ns/net"
@@ -82,6 +84,22 @@ static inline bool namespace_is_container(const char *mode)
     return false;
 }
 
+static inline bool namespace_is_bridge(const char *mode)
+{
+    if (mode != NULL && strcmp(mode, SHARE_NAMESPACE_BRIDGE) == 0) {
+        return true;
+    }
+    return false;
+}
+
+static inline bool namespace_is_file(const char *mode)
+{
+    if (mode != NULL && strcmp(mode, SHARE_NAMESPACE_FILE) == 0) {
+        return true;
+    }
+    return false;
+}
+
 static inline bool namespace_is_shareable(const char *mode)
 {
     if (mode != NULL && strcmp(mode, SHARE_NAMESPACE_SHAREABLE) == 0) {
diff --git a/src/utils/cutils/utils_file.c b/src/utils/cutils/utils_file.c
index 302e4e32..f4fa4ece 100644
--- a/src/utils/cutils/utils_file.c
+++ b/src/utils/cutils/utils_file.c
@@ -275,6 +275,29 @@ out:
     return ret;
 }
 
+bool util_force_remove_file(const char *fname, int *saved_errno)
+{
+    if (unlink(fname) == 0) {
+        return true;
+    }
+
+    WARN("Failed to delete %s: %s", fname, strerror(errno));
+    if (*saved_errno == 0) {
+        *saved_errno = errno;
+    }
+
+    if (mark_file_mutable(fname) != 0) {
+        WARN("Failed to mark file mutable");
+    }
+
+    if (unlink(fname) != 0) {
+        ERROR("Failed to delete \"%s\": %s", fname, strerror(errno));
+        return false;
+    }
+
+    return true;
+}
+
 static int recursive_rmdir_next_depth(struct stat fstat, const char *fname, int recursive_depth, int *saved_errno,
                                       int failure)
 {
diff --git a/src/utils/cutils/utils_file.h b/src/utils/cutils/utils_file.h
index 125f43a3..a7fbbb6b 100644
--- a/src/utils/cutils/utils_file.h
+++ b/src/utils/cutils/utils_file.h
@@ -36,6 +36,8 @@ bool util_file_exists(const char *f);
 
 int util_path_remove(const char *path);
 
+bool util_force_remove_file(const char *fname, int *saved_errno);
+
 ssize_t util_write_nointr(int fd, const void *buf, size_t count);
 
 ssize_t util_write_nointr_in_total(int fd, const char *buf, size_t count);
diff --git a/src/utils/cutils/utils_network.c b/src/utils/cutils/utils_network.c
new file mode 100644
index 00000000..a5d77c93
--- /dev/null
+++ b/src/utils/cutils/utils_network.c
@@ -0,0 +1,138 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *     http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: chengzeruizhi
+ * Create: 2021-11-17
+ * Description: provide common network functions
+ ********************************************************************************/
+
+#define _GNU_SOURCE
+
+#include "utils_network.h"
+
+#include <unistd.h>
+#include <sched.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/mount.h>
+#include <linux/fs.h>
+#include <syscall.h>
+#include <isula_libutils/log.h>
+#include <fcntl.h>
+
+#include "utils_fs.h"
+#include "utils_file.h"
+#include "constants.h"
+
+int util_create_netns_file(const char *netns_path)
+{
+    int ret = 0;
+    int fd = -1;
+    char *netns_dir = NULL;
+
+    if (util_file_exists(netns_path)) {
+        ERROR("Namespace file %s exists", netns_path);
+        return -1;
+    }
+    netns_dir = util_path_dir(netns_path);
+    if (netns_dir == NULL) {
+        ERROR("Failed to get path dir for %s", netns_path);
+        return -1;
+    }
+    if (!util_dir_exists(netns_dir) && util_mkdir_p(netns_dir, DEFAULT_HIGHEST_DIRECTORY_MODE) != 0) {
+        ERROR("Failed to create directory for %s", netns_path);
+        ret = -1;
+        goto out;
+    }
+
+    fd = util_open(netns_path, O_RDWR | O_CREAT | O_TRUNC, DEFAULT_SECURE_FILE_MODE);
+    if (fd < 0) {
+        ERROR("Failed to create namespace file: %s", netns_path);
+        ret = -1;
+        goto out;
+    }
+    close(fd);
+
+out:
+    free(netns_dir);
+    return ret;
+}
+
+static void mount_netns(void *netns_path)
+{
+    int failure = EXIT_FAILURE;
+    int success = EXIT_SUCCESS;
+    char fullpath[PATH_MAX] = { 0x00 };
+    int ret = 0;
+
+    if (unshare(CLONE_NEWNET) != 0) {
+        pthread_exit((void *)&failure);
+    }
+
+    ret = snprintf(fullpath, sizeof(fullpath), "/proc/%d/task/%ld/ns/net", getpid(), (long int)syscall(__NR_gettid));
+    if (ret < 0 || (size_t)ret >= sizeof(fullpath)) {
+        pthread_exit((void *)&failure);
+    }
+
+    if (util_mount(fullpath, (char *)netns_path, "none", "bind") != 0) {
+        pthread_exit((void *)&failure);
+    }
+    pthread_exit((void *)&success);
+}
+
+// this function mounts netns path to /proc/%d/task/%d/ns/net
+int util_mount_namespace(const char *netns_path)
+{
+    pthread_t newns_thread = 0;
+    int ret = 0;
+    void *status = NULL;
+
+    ret = pthread_create(&newns_thread, NULL, (void *)&mount_netns, (void *)netns_path);
+    if (ret != 0) {
+        ERROR("Failed to create thread");
+        return -1;
+    }
+
+    ret = pthread_join(newns_thread, &status);
+    if (ret != 0) {
+        ERROR("Failed to join thread");
+        return -1;
+    } else {
+        if (*(int *)status != 0) {
+            ERROR("Failed to initialize network namespace");
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int util_umount_namespace(const char *netns_path)
+{
+    int i = 0;
+    if (netns_path == NULL) {
+        WARN("Invalid path to umount");
+    }
+
+    for (i = 0; i < 50; i++) {
+        if (umount2(netns_path, MNT_DETACH) < 0) {
+            switch (errno) {
+                case EBUSY:
+                    usleep(50);
+                    continue;
+                case EINVAL:
+                    return 0;
+                default:
+                    continue;
+            }
+        }
+    }
+    ERROR("Failed to umount target %s", netns_path);
+    return -1;
+}
diff --git a/src/utils/cutils/utils_network.h b/src/utils/cutils/utils_network.h
new file mode 100644
index 00000000..6ec912d8
--- /dev/null
+++ b/src/utils/cutils/utils_network.h
@@ -0,0 +1,33 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *     http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: chengzeruizhi
+ * Create: 2021-11-17
+ * Description: provide common network functions
+ ********************************************************************************/
+
+#ifndef UTILS_CUTILS_UTILS_NETWORK_H
+#define UTILS_CUTILS_UTILS_NETWORK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int util_create_netns_file(const char *netns_path);
+
+int util_mount_namespace(const char *netns_path);
+
+int util_umount_namespace(const char *netns_path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // UTILS_CUTILS_UTILS_NETWORK_H
\ No newline at end of file
-- 
2.25.1

