1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(C) 2020 Marvell International Ltd. 3 */ 4 5 #include <fnmatch.h> 6 #include <stdbool.h> 7 8 #include <rte_common.h> 9 #include <rte_errno.h> 10 #include <rte_malloc.h> 11 #include <rte_memzone.h> 12 13 #include "graph_private.h" 14 15 static size_t 16 graph_fp_mem_calc_size(struct graph *graph) 17 { 18 struct graph_node *graph_node; 19 rte_node_t val; 20 size_t sz; 21 22 /* Graph header */ 23 sz = sizeof(struct rte_graph); 24 /* Source nodes list */ 25 sz += sizeof(rte_graph_off_t) * graph->src_node_count; 26 /* Circular buffer for pending streams of size number of nodes */ 27 val = rte_align32pow2(graph->node_count * sizeof(rte_graph_off_t)); 28 sz = RTE_ALIGN(sz, val); 29 graph->cir_start = sz; 30 graph->cir_mask = rte_align32pow2(graph->node_count) - 1; 31 sz += val; 32 /* Fence */ 33 sz += sizeof(RTE_GRAPH_FENCE); 34 sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE); 35 graph->nodes_start = sz; 36 /* For 0..N node objects with fence */ 37 STAILQ_FOREACH(graph_node, &graph->node_list, next) { 38 sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE); 39 sz += sizeof(struct rte_node); 40 /* Pointer to next nodes(edges) */ 41 sz += sizeof(struct rte_node *) * graph_node->node->nb_edges; 42 } 43 44 graph->mem_sz = sz; 45 return sz; 46 } 47 48 static void 49 graph_header_popluate(struct graph *_graph) 50 { 51 struct rte_graph *graph = _graph->graph; 52 53 graph->tail = 0; 54 graph->head = (int32_t)-_graph->src_node_count; 55 graph->cir_mask = _graph->cir_mask; 56 graph->nb_nodes = _graph->node_count; 57 graph->cir_start = RTE_PTR_ADD(graph, _graph->cir_start); 58 graph->nodes_start = _graph->nodes_start; 59 graph->socket = _graph->socket; 60 graph->id = _graph->id; 61 memcpy(graph->name, _graph->name, RTE_GRAPH_NAMESIZE); 62 graph->fence = RTE_GRAPH_FENCE; 63 } 64 65 static void 66 graph_nodes_populate(struct graph *_graph) 67 { 68 rte_graph_off_t off = _graph->nodes_start; 69 struct rte_graph *graph = _graph->graph; 70 struct graph_node *graph_node; 71 rte_edge_t count, nb_edges; 72 const char *parent; 73 rte_node_t pid; 74 75 STAILQ_FOREACH(graph_node, &_graph->node_list, next) { 76 struct rte_node *node = RTE_PTR_ADD(graph, off); 77 memset(node, 0, sizeof(*node)); 78 node->fence = RTE_GRAPH_FENCE; 79 node->off = off; 80 node->process = graph_node->node->process; 81 memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE); 82 pid = graph_node->node->parent_id; 83 if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */ 84 parent = rte_node_id_to_name(pid); 85 memcpy(node->parent, parent, RTE_GRAPH_NAMESIZE); 86 } 87 node->id = graph_node->node->id; 88 node->parent_id = pid; 89 nb_edges = graph_node->node->nb_edges; 90 node->nb_edges = nb_edges; 91 off += sizeof(struct rte_node); 92 /* Copy the name in first pass to replace with rte_node* later*/ 93 for (count = 0; count < nb_edges; count++) 94 node->nodes[count] = (struct rte_node *)&graph_node 95 ->adjacency_list[count] 96 ->node->name[0]; 97 98 off += sizeof(struct rte_node *) * nb_edges; 99 off = RTE_ALIGN(off, RTE_CACHE_LINE_SIZE); 100 node->next = off; 101 __rte_node_stream_alloc(graph, node); 102 } 103 } 104 105 struct rte_node * 106 graph_node_id_to_ptr(const struct rte_graph *graph, rte_node_t id) 107 { 108 rte_node_t count; 109 rte_graph_off_t off; 110 struct rte_node *node; 111 112 rte_graph_foreach_node(count, off, graph, node) 113 if (unlikely(node->id == id)) 114 return node; 115 116 return NULL; 117 } 118 119 struct rte_node * 120 graph_node_name_to_ptr(const struct rte_graph *graph, const char *name) 121 { 122 rte_node_t count; 123 rte_graph_off_t off; 124 struct rte_node *node; 125 126 rte_graph_foreach_node(count, off, graph, node) 127 if (strncmp(name, node->name, RTE_NODE_NAMESIZE) == 0) 128 return node; 129 130 return NULL; 131 } 132 133 static int 134 graph_node_nexts_populate(struct graph *_graph) 135 { 136 rte_node_t count, val; 137 rte_graph_off_t off; 138 struct rte_node *node; 139 const struct rte_graph *graph = _graph->graph; 140 const char *name; 141 142 rte_graph_foreach_node(count, off, graph, node) { 143 for (val = 0; val < node->nb_edges; val++) { 144 name = (const char *)node->nodes[val]; 145 node->nodes[val] = graph_node_name_to_ptr(graph, name); 146 if (node->nodes[val] == NULL) 147 SET_ERR_JMP(EINVAL, fail, "%s not found", name); 148 } 149 } 150 151 return 0; 152 fail: 153 return -rte_errno; 154 } 155 156 static int 157 graph_src_nodes_populate(struct graph *_graph) 158 { 159 struct rte_graph *graph = _graph->graph; 160 struct graph_node *graph_node; 161 struct rte_node *node; 162 int32_t head = -1; 163 const char *name; 164 165 STAILQ_FOREACH(graph_node, &_graph->node_list, next) { 166 if (graph_node->node->flags & RTE_NODE_SOURCE_F) { 167 name = graph_node->node->name; 168 node = graph_node_name_to_ptr(graph, name); 169 if (node == NULL) 170 SET_ERR_JMP(EINVAL, fail, "%s not found", name); 171 172 __rte_node_stream_alloc(graph, node); 173 graph->cir_start[head--] = node->off; 174 } 175 } 176 177 return 0; 178 fail: 179 return -rte_errno; 180 } 181 182 static int 183 graph_fp_mem_populate(struct graph *graph) 184 { 185 int rc; 186 187 graph_header_popluate(graph); 188 graph_nodes_populate(graph); 189 rc = graph_node_nexts_populate(graph); 190 rc |= graph_src_nodes_populate(graph); 191 192 return rc; 193 } 194 195 int 196 graph_fp_mem_create(struct graph *graph) 197 { 198 const struct rte_memzone *mz; 199 size_t sz; 200 201 sz = graph_fp_mem_calc_size(graph); 202 mz = rte_memzone_reserve(graph->name, sz, graph->socket, 0); 203 if (mz == NULL) 204 SET_ERR_JMP(ENOMEM, fail, "Memzone %s reserve failed", 205 graph->name); 206 207 graph->graph = mz->addr; 208 graph->mz = mz; 209 210 return graph_fp_mem_populate(graph); 211 fail: 212 return -rte_errno; 213 } 214 215 static void 216 graph_nodes_mem_destroy(struct rte_graph *graph) 217 { 218 rte_node_t count; 219 rte_graph_off_t off; 220 struct rte_node *node; 221 222 if (graph == NULL) 223 return; 224 225 rte_graph_foreach_node(count, off, graph, node) 226 rte_free(node->objs); 227 } 228 229 int 230 graph_fp_mem_destroy(struct graph *graph) 231 { 232 graph_nodes_mem_destroy(graph->graph); 233 return rte_memzone_free(graph->mz); 234 } 235