From patchwork Thu Sep 8 02:09:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Yan, Zhirun" X-Patchwork-Id: 116059 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id AE57FA0548; Thu, 8 Sep 2022 04:10:30 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5B96D427F7; Thu, 8 Sep 2022 04:10:21 +0200 (CEST) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mails.dpdk.org (Postfix) with ESMTP id 6429141155 for ; Thu, 8 Sep 2022 04:10:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1662603020; x=1694139020; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=v+ncXqIqKXoErjtYbk7ozJF9ejOhYtA287jlmKJjxs4=; b=f1RbPPfLhiGiR5OdYqWV784YRf1y4J5Ic5aX79HmTFYlQWl1Q7EGyNfU TmrvvEKnTea5Nu+ueE28hp0zMxPRHirgmHOLJTObUWF45VFE9DhBuRMJX 8sYRnVC0lC0LBEmOAQbC3opfgH+qbiXRBbcbTL1TEy5sgiQiKF/21HFbe E/rytqysdAMpAWoNxLxWVom8eQCwxYyytpFLJfbeNvNl4aNOU2IkeUJsc n/uVcXyempsA8raRTW1k6JCY8zLQtiPmlG6HiBMUxyTKTxd+DIexbGRe6 KtPWMZd+OYu723CIj2OsMYD4YGyrmv/nJCB2nsBJMNCWidMlP0r6Gk9b/ g==; X-IronPort-AV: E=McAfee;i="6500,9779,10463"; a="383336883" X-IronPort-AV: E=Sophos;i="5.93,298,1654585200"; d="scan'208";a="383336883" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Sep 2022 19:10:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.93,298,1654585200"; d="scan'208";a="565755837" Received: from dpdk-zhirun-lmm.sh.intel.com ([10.67.118.241]) by orsmga003.jf.intel.com with ESMTP; 07 Sep 2022 19:10:18 -0700 From: Zhirun Yan To: dev@dpdk.org, jerinj@marvell.com, kirankumark@marvell.com Cc: cunming.liang@intel.com, haiyue.wang@intel.com, Zhirun Yan Subject: [RFC, v1 2/6] graph: introduce graph clone API for other worker core Date: Thu, 8 Sep 2022 10:09:55 +0800 Message-Id: <20220908020959.1675953-3-zhirun.yan@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220908020959.1675953-1-zhirun.yan@intel.com> References: <20220908020959.1675953-1-zhirun.yan@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This patch adds graph API for supporting to clone the graph object for a specified worker core. The new graph will also clone all nodes. Signed-off-by: Haiyue Wang Signed-off-by: Cunming Liang Signed-off-by: Zhirun Yan --- lib/graph/graph.c | 115 ++++++++++++++++++++++++++++++++++++++ lib/graph/graph_private.h | 4 ++ lib/graph/rte_graph.h | 32 +++++++++++ lib/graph/version.map | 1 + 4 files changed, 152 insertions(+) diff --git a/lib/graph/graph.c b/lib/graph/graph.c index d61288647c..b4eb18175a 100644 --- a/lib/graph/graph.c +++ b/lib/graph/graph.c @@ -327,6 +327,8 @@ rte_graph_create(const char *name, struct rte_graph_param *prm) graph->src_node_count = src_node_count; graph->node_count = graph_nodes_count(graph); graph->id = graph_id; + graph->parent_id = RTE_GRAPH_ID_INVALID; + graph->lcore_id = RTE_MAX_LCORE; /* Allocate the Graph fast path memory and populate the data */ if (graph_fp_mem_create(graph)) @@ -387,6 +389,119 @@ rte_graph_destroy(rte_graph_t id) return rc; } +static int +clone_name(struct graph *graph, struct graph *parent_graph, const char *name) +{ + ssize_t sz, rc; + +#define SZ RTE_GRAPH_NAMESIZE + rc = rte_strscpy(graph->name, parent_graph->name, SZ); + if (rc < 0) + goto fail; + sz = rc; + rc = rte_strscpy(graph->name + sz, "-", RTE_MAX((int16_t)(SZ - sz), 0)); + if (rc < 0) + goto fail; + sz += rc; + sz = rte_strscpy(graph->name + sz, name, RTE_MAX((int16_t)(SZ - sz), 0)); + if (sz < 0) + goto fail; + + return 0; +fail: + rte_errno = E2BIG; + return -rte_errno; +} + +static rte_graph_t +graph_clone(struct graph *parent_graph, const char *name, + struct rte_graph_clone_param *prm) +{ + struct graph_node *graph_node; + struct graph *graph; + + graph_spinlock_lock(); + + if (prm->lcore_id >= RTE_MAX_LCORE) + SET_ERR_JMP(EINVAL, fail, "Invalid lcore ID"); + + /* Don't allow to clone a node from a cloned graph */ + if (parent_graph->parent_id != RTE_GRAPH_ID_INVALID) + SET_ERR_JMP(EEXIST, fail, "A cloned graph is not allowed to be cloned"); + + /* Create graph object */ + graph = calloc(1, sizeof(*graph)); + if (graph == NULL) + SET_ERR_JMP(ENOMEM, fail, "Failed to calloc cloned graph object"); + + /* Naming ceremony of the new graph. name is node->name + "-" + name */ + if (clone_name(graph, parent_graph, name)) + goto free; + + /* Check for existence of duplicate graph */ + if (rte_graph_from_name(graph->name) != RTE_GRAPH_ID_INVALID) + SET_ERR_JMP(EEXIST, free, "Found duplicate graph %s", + graph->name); + + /* Clone nodes from parent graph firstly */ + STAILQ_INIT(&graph->node_list); + STAILQ_FOREACH(graph_node, &parent_graph->node_list, next) { + if (graph_node_add(graph, graph_node->node)) + goto graph_cleanup; + } + + /* Just update adjacency list of all nodes in the graph */ + if (graph_adjacency_list_update(graph)) + goto graph_cleanup; + + /* Initialize the graph object */ + graph->src_node_count = parent_graph->src_node_count; + graph->node_count = parent_graph->node_count; + graph->parent_id = parent_graph->id; + graph->lcore_id = prm->lcore_id; + graph->socket = rte_lcore_to_socket_id(prm->lcore_id); + graph->id = graph_id; + + /* Allocate the Graph fast path memory and populate the data */ + if (graph_fp_mem_create(graph)) + goto graph_cleanup; + + /* Call init() of the all the nodes in the graph */ + if (graph_node_init(graph)) + goto graph_mem_destroy; + + /* All good, Lets add the graph to the list */ + graph_id++; + STAILQ_INSERT_TAIL(&graph_list, graph, next); + + graph_spinlock_unlock(); + return graph->id; + +graph_mem_destroy: + graph_fp_mem_destroy(graph); +graph_cleanup: + graph_cleanup(graph); +free: + free(graph); +fail: + graph_spinlock_unlock(); + return RTE_GRAPH_ID_INVALID; +} + +rte_graph_t +rte_graph_clone(rte_graph_t id, const char *name, struct rte_graph_clone_param *prm) +{ + struct graph *graph; + + GRAPH_ID_CHECK(id); + STAILQ_FOREACH(graph, &graph_list, next) + if (graph->id == id) + return graph_clone(graph, name, prm); + +fail: + return RTE_GRAPH_ID_INVALID; +} + rte_graph_t rte_graph_from_name(const char *name) { diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h index 627090f802..d53ef289d4 100644 --- a/lib/graph/graph_private.h +++ b/lib/graph/graph_private.h @@ -97,8 +97,12 @@ struct graph { /**< Circular buffer mask for wrap around. */ rte_graph_t id; /**< Graph identifier. */ + rte_graph_t parent_id; + /**< Parent graph identifier. */ size_t mem_sz; /**< Memory size of the graph. */ + unsigned int lcore_id; + /**< Lcore identifier where the grap runs on. */ int socket; /**< Socket identifier where memory is allocated. */ STAILQ_HEAD(gnode_list, graph_node) node_list; diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h index 9f84461dd8..27fd1e6cd0 100644 --- a/lib/graph/rte_graph.h +++ b/lib/graph/rte_graph.h @@ -166,6 +166,15 @@ struct rte_graph_param { /**< Array of node patterns based on shell pattern. */ }; +/** + * Structure to hold configuration parameters for cloning the graph. + * + * @see rte_graph_clone() + */ +struct rte_graph_clone_param { + unsigned int lcore_id; /**< Lcore id where the new graph is cloned to run. */ +}; + /** * Structure to hold configuration parameters for graph cluster stats create. * @@ -242,6 +251,29 @@ rte_graph_t rte_graph_create(const char *name, struct rte_graph_param *prm); __rte_experimental int rte_graph_destroy(rte_graph_t id); +/** + * Clone Graph. + * + * Clone a graph from static graph (graph created from rte_graph_create). And + * all cloned graphs attached to the parent graph MUST be destroied together + * for fast schedule design limitation (stop ALL graph walk firstly). + * + * @param id + * Static graph id to clone from. + * @param name + * Name of the new graph. The library prepends the parent graph name to the + * user-specified name. The final graph name will be, + * "parent graph name" + "-" + name. + * @param prm + * Graph clone parameter, includes lcore ID. + * + * @return + * Valid graph id on success, RTE_GRAPH_ID_INVALID otherwise. + */ +__rte_experimental +rte_graph_t rte_graph_clone(rte_graph_t id, const char *name, + struct rte_graph_clone_param *prm); + /** * Get graph id from graph name. * diff --git a/lib/graph/version.map b/lib/graph/version.map index 6d40a74731..6fc43e4411 100644 --- a/lib/graph/version.map +++ b/lib/graph/version.map @@ -5,6 +5,7 @@ EXPERIMENTAL { __rte_node_stream_alloc; __rte_node_stream_alloc_size; + rte_graph_clone; rte_graph_create; rte_graph_destroy; rte_graph_dump;