From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <dev-bounces@dpdk.org> Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0A40CA057C; Thu, 26 Mar 2020 17:57:58 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id BAB821C0C0; Thu, 26 Mar 2020 17:57:01 +0100 (CET) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by dpdk.org (Postfix) with ESMTP id 0C6FE1AFF for <dev@dpdk.org>; Thu, 26 Mar 2020 17:56:59 +0100 (CET) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 02QGiftN025353; Thu, 26 Mar 2020 09:56:57 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0818; bh=iZK1spM6xWPon4J6SyXXhBuV73U1XyD4snNdIZ7/Rzc=; b=S54hHj4WopPzc8bcHbwlQFfYOHthaMzmbmrE5LcBUFbPzsunR7DmRxsGR64uzSCLpFKq HnTYWuFyWQFlExIuq/QewLm/h4Lj2hV8a5s1FXwHxuzBSP9BSn8s7FDqTuWhpiCNCJSI W2i84ltSes5vgMSiy7eLS4hB+KYfnD4zxVUg4cNGsZSz6xHdBprzslhTKejYcSx62K8N q0JoXjSjMS6w2lsorlsR6+BLZ5Lp0Grohqe5mDH3jANOIvBJLr8o5KE6gjB9xyad4Qrw DF7SOBihp0uJypVV0YcAPtkBtPDqxst6k+C0JgGQNbIKkqAiZWULaK7MpvIR3VCDNqkA vw== Received: from sc-exch02.marvell.com ([199.233.58.182]) by mx0a-0016f401.pphosted.com with ESMTP id 2ywg9nxgfa-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Thu, 26 Mar 2020 09:56:57 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by SC-EXCH02.marvell.com (10.93.176.82) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 26 Mar 2020 09:56:56 -0700 Received: from SC-EXCH03.marvell.com (10.93.176.83) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 26 Mar 2020 09:56:55 -0700 Received: from maili.marvell.com (10.93.176.43) by SC-EXCH03.marvell.com (10.93.176.83) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Thu, 26 Mar 2020 09:56:54 -0700 Received: from jerin-lab.marvell.com (jerin-lab.marvell.com [10.28.34.14]) by maili.marvell.com (Postfix) with ESMTP id 6DFAF3F7040; Thu, 26 Mar 2020 09:56:52 -0700 (PDT) From: <jerinj@marvell.com> To: Jerin Jacob <jerinj@marvell.com>, Kiran Kumar K <kirankumark@marvell.com> CC: <dev@dpdk.org>, <thomas@monjalon.net>, <david.marchand@redhat.com>, <mdr@ashroe.eu>, <mattias.ronnblom@ericsson.com>, <pbhagavatula@marvell.com>, <ndabilpuram@marvell.com> Date: Thu, 26 Mar 2020 22:26:23 +0530 Message-ID: <20200326165644.866053-8-jerinj@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200326165644.866053-1-jerinj@marvell.com> References: <20200318213551.3489504-1-jerinj@marvell.com> <20200326165644.866053-1-jerinj@marvell.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.645 definitions=2020-03-26_08:2020-03-26, 2020-03-26 signatures=0 Subject: [dpdk-dev] [PATCH v2 07/28] graph: implement create and destroy APIs X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions <dev.dpdk.org> List-Unsubscribe: <https://mails.dpdk.org/options/dev>, <mailto:dev-request@dpdk.org?subject=unsubscribe> List-Archive: <http://mails.dpdk.org/archives/dev/> List-Post: <mailto:dev@dpdk.org> List-Help: <mailto:dev-request@dpdk.org?subject=help> List-Subscribe: <https://mails.dpdk.org/listinfo/dev>, <mailto:dev-request@dpdk.org?subject=subscribe> Errors-To: dev-bounces@dpdk.org Sender: "dev" <dev-bounces@dpdk.org> From: Jerin Jacob <jerinj@marvell.com> Adding graph specific API implementations like graph create and graph destroy. This detect loops in the graph, check for isolated nodes and operation to verify the validity of graph. Signed-off-by: Jerin Jacob <jerinj@marvell.com> Signed-off-by: Kiran Kumar K <kirankumark@marvell.com> Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> --- lib/librte_graph/graph.c | 320 +++++++++++++++++++++++++ lib/librte_graph/rte_graph_version.map | 2 + 2 files changed, 322 insertions(+) diff --git a/lib/librte_graph/graph.c b/lib/librte_graph/graph.c index e1930b7d2..dc373231e 100644 --- a/lib/librte_graph/graph.c +++ b/lib/librte_graph/graph.c @@ -2,13 +2,33 @@ * Copyright(C) 2020 Marvell International Ltd. */ +#include <fnmatch.h> +#include <stdbool.h> + +#include <rte_common.h> +#include <rte_debug.h> +#include <rte_errno.h> #include <rte_malloc.h> +#include <rte_memzone.h> #include <rte_spinlock.h> +#include <rte_string_fns.h> #include "graph_private.h" +static struct graph_head graph_list = STAILQ_HEAD_INITIALIZER(graph_list); static rte_spinlock_t graph_lock = RTE_SPINLOCK_INITIALIZER; +static rte_graph_t graph_id; int rte_graph_logtype; + +#define GRAPH_ID_CHECK(id) ID_CHECK(id, graph_id) + +/* Private functions */ +struct graph_head * +graph_list_head_get(void) +{ + return &graph_list; +} + void graph_spinlock_lock(void) { @@ -21,6 +41,306 @@ graph_spinlock_unlock(void) rte_spinlock_unlock(&graph_lock); } +static int +graph_node_add(struct graph *graph, struct node *node) +{ + struct graph_node *graph_node; + size_t sz; + + /* Skip the duplicate nodes */ + STAILQ_FOREACH(graph_node, &graph->node_list, next) + if (strncmp(node->name, graph_node->node->name, + RTE_NODE_NAMESIZE) == 0) + return 0; + + /* Allocate new graph node object */ + sz = sizeof(*graph_node) + node->nb_edges * sizeof(struct node *); + graph_node = calloc(1, sz); + + if (graph_node == NULL) + SET_ERR_JMP(ENOMEM, free, "Failed to calloc %s object", + node->name); + + /* Initialize the graph node */ + graph_node->node = node; + + /* Add to graph node list */ + STAILQ_INSERT_TAIL(&graph->node_list, graph_node, next); + return 0; + +free: + free(graph_node); + return -rte_errno; +} + +static struct graph_node * +node_to_graph_node(struct graph *graph, struct node *node) +{ + struct graph_node *graph_node; + + STAILQ_FOREACH(graph_node, &graph->node_list, next) + if (graph_node->node == node) + return graph_node; + + SET_ERR_JMP(ENODEV, fail, "Found isolated node %s", node->name); +fail: + return NULL; +} + +static int +graph_node_edges_add(struct graph *graph) +{ + struct graph_node *graph_node; + struct node *adjacency; + const char *next; + rte_edge_t i; + + STAILQ_FOREACH(graph_node, &graph->node_list, next) { + for (i = 0; i < graph_node->node->nb_edges; i++) { + next = graph_node->node->next_nodes[i]; + adjacency = node_from_name(next); + if (adjacency == NULL) + SET_ERR_JMP(EINVAL, fail, + "Node %s not registered", next); + if (graph_node_add(graph, adjacency)) + goto fail; + } + } + return 0; +fail: + return -rte_errno; +} + +static int +graph_adjacency_list_update(struct graph *graph) +{ + struct graph_node *graph_node, *tmp; + struct node *adjacency; + const char *next; + rte_edge_t i; + + STAILQ_FOREACH(graph_node, &graph->node_list, next) { + for (i = 0; i < graph_node->node->nb_edges; i++) { + next = graph_node->node->next_nodes[i]; + adjacency = node_from_name(next); + if (adjacency == NULL) + SET_ERR_JMP(EINVAL, fail, + "Node %s not registered", next); + tmp = node_to_graph_node(graph, adjacency); + if (tmp == NULL) + goto fail; + graph_node->adjacency_list[i] = tmp; + } + } + + return 0; +fail: + return -rte_errno; +} + +static int +expand_pattern_to_node(struct graph *graph, const char *pattern) +{ + struct node_head *node_head = node_list_head_get(); + bool found = false; + struct node *node; + + /* Check for pattern match */ + STAILQ_FOREACH(node, node_head, next) { + if (fnmatch(pattern, node->name, 0) == 0) { + if (graph_node_add(graph, node)) + goto fail; + found = true; + } + } + if (found == false) + SET_ERR_JMP(EFAULT, fail, "Pattern %s node not found", pattern); + + return 0; +fail: + return -rte_errno; +} + +static void +graph_cleanup(struct graph *graph) +{ + struct graph_node *graph_node; + + while (!STAILQ_EMPTY(&graph->node_list)) { + graph_node = STAILQ_FIRST(&graph->node_list); + STAILQ_REMOVE_HEAD(&graph->node_list, next); + free(graph_node); + } +} + +static int +graph_node_init(struct graph *graph) +{ + struct graph_node *graph_node; + const char *name; + int rc; + + STAILQ_FOREACH(graph_node, &graph->node_list, next) { + if (graph_node->node->init) { + name = graph_node->node->name; + rc = graph_node->node->init( + graph->graph, + graph_node_name_to_ptr(graph->graph, name)); + if (rc) + SET_ERR_JMP(rc, err, "Node %s init() failed", + name); + } + } + + return 0; +err: + return -rte_errno; +} + +static void +graph_node_fini(struct graph *graph) +{ + struct graph_node *graph_node; + + STAILQ_FOREACH(graph_node, &graph->node_list, next) + if (graph_node->node->fini) + graph_node->node->fini( + graph->graph, + graph_node_name_to_ptr(graph->graph, + graph_node->node->name)); +} + +rte_graph_t +rte_graph_create(const char *name, struct rte_graph_param *prm) +{ + struct graph *graph; + const char *pattern; + uint16_t i; + + graph_spinlock_lock(); + + /* Check arguments sanity */ + if (prm == NULL) + SET_ERR_JMP(EINVAL, fail, "Param should not be NULL"); + + if (name == NULL) + SET_ERR_JMP(EINVAL, fail, "Graph name should not be NULL"); + + /* Check for existence of duplicate graph */ + STAILQ_FOREACH(graph, &graph_list, next) + if (strncmp(name, graph->name, RTE_GRAPH_NAMESIZE) == 0) + SET_ERR_JMP(EEXIST, fail, "Found duplicate graph %s", + name); + + /* Create graph object */ + graph = calloc(1, sizeof(*graph)); + if (graph == NULL) + SET_ERR_JMP(ENOMEM, fail, "Failed to calloc graph object"); + + /* Initialize the graph object */ + STAILQ_INIT(&graph->node_list); + if (rte_strscpy(graph->name, name, RTE_GRAPH_NAMESIZE) < 0) + SET_ERR_JMP(E2BIG, free, "Too big name=%s", name); + + /* Expand node pattern and add the nodes to the graph */ + for (i = 0; i < prm->nb_node_patterns; i++) { + pattern = prm->node_patterns[i]; + if (expand_pattern_to_node(graph, pattern)) + goto graph_cleanup; + } + + /* Go over all the nodes edges and add them to the graph */ + if (graph_node_edges_add(graph)) + goto graph_cleanup; + + /* Update adjacency list of all nodes in the graph */ + if (graph_adjacency_list_update(graph)) + goto graph_cleanup; + + /* Make sure at least a source node present in the graph */ + if (!graph_src_nodes_count(graph)) + goto graph_cleanup; + + /* Make sure no node is pointing to source node */ + if (graph_node_has_edge_to_src_node(graph)) + goto graph_cleanup; + + /* Don't allow node has loop to self */ + if (graph_node_has_loop_edge(graph)) + goto graph_cleanup; + + /* Do BFS from src nodes on the graph to find isolated nodes */ + if (graph_has_isolated_node(graph)) + goto graph_cleanup; + + /* Initialize graph object */ + graph->socket = prm->socket_id; + graph->src_node_count = graph_src_nodes_count(graph); + graph->node_count = graph_nodes_count(graph); + 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_destroy(const char *graph_name) +{ + rte_graph_t rc = RTE_GRAPH_ID_INVALID; + struct graph *graph, *tmp; + const char *name; + + graph_spinlock_lock(); + + graph = STAILQ_FIRST(&graph_list); + while (graph != NULL) { + tmp = STAILQ_NEXT(graph, next); + name = graph->name; + if (strncmp(name, graph_name, RTE_GRAPH_NAMESIZE) == 0) { + /* Call fini() of the all the nodes in the graph */ + graph_node_fini(graph); + /* Destroy graph fast path memory */ + rc = graph_fp_mem_destroy(graph); + if (rc) + SET_ERR_JMP(rc, done, "MZ %s free failed", + name); + + graph_cleanup(graph); + STAILQ_REMOVE(&graph_list, graph, graph, next); + rc = graph->id; + free(graph); + graph_id--; + goto done; + } + graph = tmp; + } +done: + graph_spinlock_unlock(); + return rc; +} + void __rte_noinline __rte_node_stream_alloc(struct rte_graph *graph, struct rte_node *node) { diff --git a/lib/librte_graph/rte_graph_version.map b/lib/librte_graph/rte_graph_version.map index a9fe1b610..dcbd78c02 100644 --- a/lib/librte_graph/rte_graph_version.map +++ b/lib/librte_graph/rte_graph_version.map @@ -4,6 +4,8 @@ EXPERIMENTAL { __rte_node_register; __rte_node_stream_alloc; + rte_graph_create; + rte_graph_destroy; rte_node_clone; rte_node_dump; rte_node_edge_count; -- 2.25.1