1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2020 Marvell International Ltd.
9 #include <rte_common.h>
10 #include <rte_debug.h>
12 #include <rte_errno.h>
13 #include <rte_string_fns.h>
15 #include "graph_private.h"
17 static struct node_head node_list = STAILQ_HEAD_INITIALIZER(node_list);
18 static rte_node_t node_id;
20 #define NODE_ID_CHECK(id) ID_CHECK(id, node_id)
22 /* Private functions */
24 node_list_head_get(void)
30 node_from_name(const char *name)
34 STAILQ_FOREACH(node, &node_list, next)
35 if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0)
42 node_has_duplicate_entry(const char *name)
46 /* Is duplicate name registered */
47 STAILQ_FOREACH(node, &node_list, next) {
48 if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0) {
56 /* Public functions */
58 __rte_node_register(const struct rte_node_register *reg)
64 /* Limit Node specific metadata to one cacheline on 64B CL machine */
65 RTE_BUILD_BUG_ON((offsetof(struct rte_node, nodes) -
66 offsetof(struct rte_node, ctx)) !=
67 RTE_CACHE_LINE_MIN_SIZE);
69 graph_spinlock_lock();
72 if (reg == NULL || reg->process == NULL) {
77 /* Check for duplicate name */
78 if (node_has_duplicate_entry(reg->name))
81 sz = sizeof(struct node) + (reg->nb_edges * RTE_NODE_NAMESIZE);
88 /* Initialize the node */
89 if (rte_strscpy(node->name, reg->name, RTE_NODE_NAMESIZE) < 0)
91 node->flags = reg->flags;
92 node->process = reg->process;
93 node->init = reg->init;
94 node->fini = reg->fini;
95 node->nb_edges = reg->nb_edges;
96 node->parent_id = reg->parent_id;
97 for (i = 0; i < reg->nb_edges; i++) {
98 if (rte_strscpy(node->next_nodes[i], reg->next_nodes[i],
99 RTE_NODE_NAMESIZE) < 0)
103 node->id = node_id++;
105 /* Add the node at tail */
106 STAILQ_INSERT_TAIL(&node_list, node, next);
107 graph_spinlock_unlock();
113 graph_spinlock_unlock();
114 return RTE_NODE_ID_INVALID;
118 clone_name(struct rte_node_register *reg, struct node *node, const char *name)
122 #define SZ RTE_NODE_NAMESIZE
123 rc = rte_strscpy(reg->name, node->name, SZ);
127 rc = rte_strscpy(reg->name + sz, "-", RTE_MAX((int16_t)(SZ - sz), 0));
131 sz = rte_strscpy(reg->name + sz, name, RTE_MAX((int16_t)(SZ - sz), 0));
142 node_clone(struct node *node, const char *name)
144 rte_node_t rc = RTE_NODE_ID_INVALID;
145 struct rte_node_register *reg;
148 /* Don't allow to clone a node from a cloned node */
149 if (node->parent_id != RTE_NODE_ID_INVALID) {
154 /* Check for duplicate name */
155 if (node_has_duplicate_entry(name))
158 reg = calloc(1, sizeof(*reg) + (sizeof(char *) * node->nb_edges));
164 /* Clone the source node */
165 reg->flags = node->flags;
166 reg->process = node->process;
167 reg->init = node->init;
168 reg->fini = node->fini;
169 reg->nb_edges = node->nb_edges;
170 reg->parent_id = node->id;
172 for (i = 0; i < node->nb_edges; i++)
173 reg->next_nodes[i] = node->next_nodes[i];
175 /* Naming ceremony of the new node. name is node->name + "-" + name */
176 if (clone_name(reg, node, name))
179 rc = __rte_node_register(reg);
187 rte_node_clone(rte_node_t id, const char *name)
192 STAILQ_FOREACH(node, &node_list, next)
194 return node_clone(node, name);
197 return RTE_NODE_ID_INVALID;
201 rte_node_from_name(const char *name)
205 STAILQ_FOREACH(node, &node_list, next)
206 if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0)
209 return RTE_NODE_ID_INVALID;
213 rte_node_id_to_name(rte_node_t id)
218 STAILQ_FOREACH(node, &node_list, next)
227 rte_node_edge_count(rte_node_t id)
232 STAILQ_FOREACH(node, &node_list, next)
234 return node->nb_edges;
236 return RTE_EDGE_ID_INVALID;
240 edge_update(struct node *node, struct node *prev, rte_edge_t from,
241 const char **next_nodes, rte_edge_t nb_edges)
243 rte_edge_t i, max_edges, count = 0;
244 struct node *new_node;
248 if (from == RTE_EDGE_ID_INVALID)
249 from = node->nb_edges;
251 /* Don't create hole in next_nodes[] list */
252 if (from > node->nb_edges) {
257 /* Remove me from list */
258 STAILQ_REMOVE(&node_list, node, node, next);
260 /* Allocate the storage space for new node if required */
261 max_edges = from + nb_edges;
262 need_realloc = max_edges > node->nb_edges;
264 sz = sizeof(struct node) + (max_edges * RTE_NODE_NAMESIZE);
265 new_node = realloc(node, sz);
266 if (new_node == NULL) {
274 /* Update the new nodes name */
275 for (i = from; i < max_edges; i++, count++) {
276 if (rte_strscpy(node->next_nodes[i], next_nodes[count],
277 RTE_NODE_NAMESIZE) < 0)
281 /* Update the linked list to point new node address in prev node */
283 STAILQ_INSERT_AFTER(&node_list, prev, node, next);
285 STAILQ_INSERT_HEAD(&node_list, node, next);
288 node->nb_edges = max_edges;
295 rte_node_edge_shrink(rte_node_t id, rte_edge_t size)
297 rte_edge_t rc = RTE_EDGE_ID_INVALID;
301 graph_spinlock_lock();
303 STAILQ_FOREACH(node, &node_list, next) {
304 if (node->id == id) {
305 if (node->nb_edges < size) {
309 node->nb_edges = size;
316 graph_spinlock_unlock();
321 rte_node_edge_update(rte_node_t id, rte_edge_t from, const char **next_nodes,
324 rte_edge_t rc = RTE_EDGE_ID_INVALID;
325 struct node *n, *prev;
328 graph_spinlock_lock();
331 STAILQ_FOREACH(n, &node_list, next) {
333 rc = edge_update(n, prev, from, next_nodes, nb_edges);
339 graph_spinlock_unlock();
345 node_copy_edges(struct node *node, char *next_nodes[])
349 for (i = 0; i < node->nb_edges; i++)
350 next_nodes[i] = node->next_nodes[i];
356 rte_node_edge_get(rte_node_t id, char *next_nodes[])
358 rte_node_t rc = RTE_NODE_ID_INVALID;
362 graph_spinlock_lock();
364 STAILQ_FOREACH(node, &node_list, next) {
365 if (node->id == id) {
366 if (next_nodes == NULL)
367 rc = sizeof(char *) * node->nb_edges;
369 rc = node_copy_edges(node, next_nodes);
374 graph_spinlock_unlock();
380 node_scan_dump(FILE *f, rte_node_t id, bool all)
384 RTE_ASSERT(f != NULL);
387 STAILQ_FOREACH(node, &node_list, next) {
390 } else if (node->id == id) {
400 rte_node_dump(FILE *f, rte_node_t id)
402 node_scan_dump(f, id, false);
406 rte_node_list_dump(FILE *f)
408 node_scan_dump(f, 0, true);
412 rte_node_max_count(void)