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 43 graph->mem_sz = sz; 44 return sz; 45 } 46 47 static void 48 graph_header_popluate(struct graph *_graph) 49 { 50 struct rte_graph *graph = _graph->graph; 51 52 graph->tail = 0; 53 graph->head = (int32_t)-_graph->src_node_count; 54 graph->cir_mask = _graph->cir_mask; 55 graph->nb_nodes = _graph->node_count; 56 graph->cir_start = RTE_PTR_ADD(graph, _graph->cir_start); 57 graph->nodes_start = _graph->nodes_start; 58 graph->socket = _graph->socket; 59 graph->id = _graph->id; 60 memcpy(graph->name, _graph->name, RTE_GRAPH_NAMESIZE); 61 graph->fence = RTE_GRAPH_FENCE; 62 } 63 64 static void 65 graph_nodes_populate(struct graph *_graph) 66 { 67 rte_graph_off_t off = _graph->nodes_start; 68 struct rte_graph *graph = _graph->graph; 69 struct graph_node *graph_node; 70 rte_edge_t count, nb_edges; 71 const char *parent; 72 rte_node_t pid; 73 74 STAILQ_FOREACH(graph_node, &_graph->node_list, next) { 75 struct rte_node *node = RTE_PTR_ADD(graph, off); 76 memset(node, 0, sizeof(*node)); 77 node->fence = RTE_GRAPH_FENCE; 78 node->off = off; 79 if (graph_pcap_is_enable()) { 80 node->process = graph_pcap_dispatch; 81 node->original_process = graph_node->node->process; 82 } else 83 node->process = graph_node->node->process; 84 memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE); 85 pid = graph_node->node->parent_id; 86 if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */ 87 parent = rte_node_id_to_name(pid); 88 memcpy(node->parent, parent, RTE_GRAPH_NAMESIZE); 89 } 90 node->id = graph_node->node->id; 91 node->parent_id = pid; 92 node->dispatch.lcore_id = graph_node->node->lcore_id; 93 nb_edges = graph_node->node->nb_edges; 94 node->nb_edges = nb_edges; 95 off += sizeof(struct rte_node); 96 /* Copy the name in first pass to replace with rte_node* later*/ 97 for (count = 0; count < nb_edges; count++) 98 node->nodes[count] = (struct rte_node *)&graph_node 99 ->adjacency_list[count] 100 ->node->name[0]; 101 102 off += sizeof(struct rte_node *) * nb_edges; 103 off = RTE_ALIGN(off, RTE_CACHE_LINE_SIZE); 104 node->next = off; 105 __rte_node_stream_alloc(graph, node); 106 } 107 } 108 109 struct rte_node * 110 graph_node_id_to_ptr(const struct rte_graph *graph, rte_node_t id) 111 { 112 rte_node_t count; 113 rte_graph_off_t off; 114 struct rte_node *node; 115 116 rte_graph_foreach_node(count, off, graph, node) 117 if (unlikely(node->id == id)) 118 return node; 119 120 return NULL; 121 } 122 123 struct rte_node * 124 graph_node_name_to_ptr(const struct rte_graph *graph, const char *name) 125 { 126 rte_node_t count; 127 rte_graph_off_t off; 128 struct rte_node *node; 129 130 rte_graph_foreach_node(count, off, graph, node) 131 if (strncmp(name, node->name, RTE_NODE_NAMESIZE) == 0) 132 return node; 133 134 return NULL; 135 } 136 137 static int 138 graph_node_nexts_populate(struct graph *_graph) 139 { 140 rte_node_t count, val; 141 rte_graph_off_t off; 142 struct rte_node *node; 143 const struct rte_graph *graph = _graph->graph; 144 const char *name; 145 146 rte_graph_foreach_node(count, off, graph, node) { 147 for (val = 0; val < node->nb_edges; val++) { 148 name = (const char *)node->nodes[val]; 149 node->nodes[val] = graph_node_name_to_ptr(graph, name); 150 if (node->nodes[val] == NULL) 151 SET_ERR_JMP(EINVAL, fail, "%s not found", name); 152 } 153 } 154 155 return 0; 156 fail: 157 return -rte_errno; 158 } 159 160 static int 161 graph_src_nodes_populate(struct graph *_graph) 162 { 163 struct rte_graph *graph = _graph->graph; 164 struct graph_node *graph_node; 165 struct rte_node *node; 166 int32_t head = -1; 167 const char *name; 168 169 STAILQ_FOREACH(graph_node, &_graph->node_list, next) { 170 if (graph_node->node->flags & RTE_NODE_SOURCE_F) { 171 name = graph_node->node->name; 172 node = graph_node_name_to_ptr(graph, name); 173 if (node == NULL) 174 SET_ERR_JMP(EINVAL, fail, "%s not found", name); 175 176 __rte_node_stream_alloc(graph, node); 177 graph->cir_start[head--] = node->off; 178 } 179 } 180 181 return 0; 182 fail: 183 return -rte_errno; 184 } 185 186 static int 187 graph_fp_mem_populate(struct graph *graph) 188 { 189 int rc; 190 191 graph_header_popluate(graph); 192 if (graph_pcap_is_enable()) 193 graph_pcap_init(graph); 194 graph_nodes_populate(graph); 195 rc = graph_node_nexts_populate(graph); 196 rc |= graph_src_nodes_populate(graph); 197 198 return rc; 199 } 200 201 int 202 graph_fp_mem_create(struct graph *graph) 203 { 204 const struct rte_memzone *mz; 205 size_t sz; 206 207 sz = graph_fp_mem_calc_size(graph); 208 mz = rte_memzone_reserve(graph->name, sz, graph->socket, 0); 209 if (mz == NULL) 210 SET_ERR_JMP(ENOMEM, fail, "Memzone %s reserve failed", 211 graph->name); 212 213 graph->graph = mz->addr; 214 graph->mz = mz; 215 216 return graph_fp_mem_populate(graph); 217 fail: 218 return -rte_errno; 219 } 220 221 static void 222 graph_nodes_mem_destroy(struct rte_graph *graph) 223 { 224 rte_node_t count; 225 rte_graph_off_t off; 226 struct rte_node *node; 227 228 if (graph == NULL) 229 return; 230 231 rte_graph_foreach_node(count, off, graph, node) 232 rte_free(node->objs); 233 } 234 235 int 236 graph_fp_mem_destroy(struct graph *graph) 237 { 238 if (graph_pcap_is_enable()) 239 graph_pcap_exit(graph->graph); 240 241 graph_nodes_mem_destroy(graph->graph); 242 return rte_memzone_free(graph->mz); 243 } 244