xref: /dpdk/lib/graph/graph_populate.c (revision 7f9326423a045f7346a459280dc98fed4afd6811)
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