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