/
phprus
/
github_dpdk
Обзор
Документация
Войти
/
phprus
/
github_dpdk
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
lib/graph/node.c
548 строк
11 KB
Luca Boccassi
doc: fix grammar after the verb allow
01 июн 2026, 16:02
01 июн 2026, 16:02
a14bda0
Код
Авторство
О чём код?
/* SPDX-License-Identifier: BSD-3-Clause * Copyright(C) 2020 Marvell International Ltd. */ #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <eal_export.h> #include <rte_common.h> #include <rte_debug.h> #include <rte_errno.h> #include <rte_string_fns.h> #include "graph_private.h" static struct node_head node_list = STAILQ_HEAD_INITIALIZER(node_list); static struct node * node_from_id(rte_node_t id) { struct node *node = NULL; graph_spinlock_lock(); rte_errno = EINVAL; STAILQ_FOREACH(node, &node_list, next) { if (node->id == id) { rte_errno = 0; goto exit; } } exit: graph_spinlock_unlock(); return node; } static rte_node_t next_next_free_id(void) { struct node *node; rte_node_t id = 0; STAILQ_FOREACH(node, &node_list, next) { if (id < node->id) break; id = node->id + 1; } return id; } static void node_insert_ordered(struct node *node) { struct node *after, *g; after = NULL; STAILQ_FOREACH(g, &node_list, next) { if (g->id < node->id) after = g; else if (g->id > node->id) break; } if (after == NULL) STAILQ_INSERT_HEAD(&node_list, node, next); else STAILQ_INSERT_AFTER(&node_list, after, node, next); } /* Private functions */ struct node_head * node_list_head_get(void) { return &node_list; } struct node * node_from_name(const char *name) { struct node *node; STAILQ_FOREACH(node, &node_list, next) if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0) return node; return NULL; } static bool node_has_duplicate_entry(const char *name) { struct node *node; /* Is duplicate name registered */ STAILQ_FOREACH(node, &node_list, next) { if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0) { rte_errno = EEXIST; return 1; } } return 0; } /* Public functions */ RTE_EXPORT_SYMBOL(__rte_node_register) rte_node_t __rte_node_register(const struct rte_node_register *reg) { struct node *node; rte_edge_t i; size_t sz; /* Limit Node specific metadata to one cacheline on 64B CL machine */ RTE_BUILD_BUG_ON((offsetof(struct rte_node, nodes) - offsetof(struct rte_node, ctx)) != RTE_CACHE_LINE_MIN_SIZE); graph_spinlock_lock(); /* Check sanity */ if (reg == NULL || reg->process == NULL) { rte_errno = EINVAL; goto fail; } /* Check for duplicate name */ if (node_has_duplicate_entry(reg->name)) goto fail; sz = sizeof(struct node) + (reg->nb_edges * RTE_NODE_NAMESIZE); node = calloc(1, sz); if (node == NULL) { rte_errno = ENOMEM; goto fail; } if (reg->xstats) { sz = sizeof(*reg->xstats) + (reg->xstats->nb_xstats * RTE_NODE_XSTAT_DESC_SIZE); node->xstats = calloc(1, sz); if (node->xstats == NULL) { rte_errno = ENOMEM; goto free; } node->xstats->nb_xstats = reg->xstats->nb_xstats; for (i = 0; i < reg->xstats->nb_xstats; i++) if (rte_strscpy(node->xstats->xstat_desc[i], reg->xstats->xstat_desc[i], RTE_NODE_XSTAT_DESC_SIZE) < 0) goto free_xstat; } /* Initialize the node */ if (rte_strscpy(node->name, reg->name, RTE_NODE_NAMESIZE) < 0) goto free_xstat; node->flags = reg->flags; node->process = reg->process; node->init = reg->init; node->fini = reg->fini; node->nb_edges = reg->nb_edges; node->parent_id = reg->parent_id; for (i = 0; i < reg->nb_edges; i++) { if (rte_strscpy(node->next_nodes[i], reg->next_nodes[i], RTE_NODE_NAMESIZE) < 0) goto free_xstat; } node->lcore_id = RTE_MAX_LCORE; node->id = next_next_free_id(); /* Add the node in ordered list */ node_insert_ordered(node); graph_spinlock_unlock(); return node->id; free_xstat: free(node->xstats); free: free(node); fail: graph_spinlock_unlock(); return RTE_NODE_ID_INVALID; } static rte_node_t node_clone(struct node *node, const char *name) { rte_node_t rc = RTE_NODE_ID_INVALID; struct rte_node_register *reg; rte_edge_t i; /* Don't allow cloning a node from a cloned node */ if (node->parent_id != RTE_NODE_ID_INVALID) { rte_errno = EEXIST; goto fail; } reg = calloc(1, sizeof(*reg) + (sizeof(char *) * node->nb_edges)); if (reg == NULL) { rte_errno = ENOMEM; goto fail; } if (node->xstats) { reg->xstats = calloc(1, sizeof(*node->xstats) + (node->xstats->nb_xstats * RTE_NODE_XSTAT_DESC_SIZE)); if (reg->xstats == NULL) { rte_errno = ENOMEM; goto free; } for (i = 0; i < node->xstats->nb_xstats; i++) if (rte_strscpy(reg->xstats->xstat_desc[i], node->xstats->xstat_desc[i], RTE_NODE_XSTAT_DESC_SIZE) < 0) goto free_xstat; } /* Clone the source node */ reg->flags = node->flags; reg->process = node->process; reg->init = node->init; reg->fini = node->fini; reg->nb_edges = node->nb_edges; reg->parent_id = node->id; for (i = 0; i < node->nb_edges; i++) reg->next_nodes[i] = node->next_nodes[i]; /* Naming ceremony of the new node. name is node->name + "-" + name */ if (clone_name(reg->name, node->name, name)) goto free_xstat; rc = __rte_node_register(reg); free_xstat: free(reg->xstats); free: free(reg); fail: return rc; } RTE_EXPORT_SYMBOL(rte_node_clone) rte_node_t rte_node_clone(rte_node_t id, const char *name) { struct node *node; if (node_from_id(id) == NULL) goto fail; STAILQ_FOREACH(node, &node_list, next) if (node->id == id) return node_clone(node, name); fail: return RTE_NODE_ID_INVALID; } RTE_EXPORT_SYMBOL(rte_node_from_name) rte_node_t rte_node_from_name(const char *name) { struct node *node; STAILQ_FOREACH(node, &node_list, next) if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0) return node->id; return RTE_NODE_ID_INVALID; } RTE_EXPORT_SYMBOL(rte_node_id_to_name) char * rte_node_id_to_name(rte_node_t id) { struct node *node; if (node_from_id(id) == NULL) goto fail; STAILQ_FOREACH(node, &node_list, next) if (node->id == id) return node->name; fail: return NULL; } RTE_EXPORT_SYMBOL(rte_node_edge_count) rte_edge_t rte_node_edge_count(rte_node_t id) { struct node *node; if (node_from_id(id) == NULL) goto fail; STAILQ_FOREACH(node, &node_list, next) if (node->id == id) return node->nb_edges; fail: return RTE_EDGE_ID_INVALID; } static rte_edge_t edge_update(struct node *node, struct node *prev, rte_edge_t from, const char **next_nodes, rte_edge_t nb_edges) { rte_edge_t i, max_edges, count = 0; struct node *new_node; bool need_realloc; size_t sz; if (from == RTE_EDGE_ID_INVALID) from = node->nb_edges; /* Don't create hole in next_nodes[] list */ if (from > node->nb_edges) { rte_errno = ENOMEM; goto fail; } /* Remove me from list */ STAILQ_REMOVE(&node_list, node, node, next); /* Allocate the storage space for new node if required */ max_edges = from + nb_edges; need_realloc = max_edges > node->nb_edges; if (need_realloc) { sz = sizeof(struct node) + (max_edges * RTE_NODE_NAMESIZE); new_node = malloc(sz); if (new_node == NULL) { rte_errno = ENOMEM; goto restore; } else { sz = sizeof(*node) + (node->nb_edges * RTE_NODE_NAMESIZE); memcpy(new_node, node, sz); graph_node_replace_all(node, new_node); free(node); node = new_node; } } /* Update the new nodes name */ for (i = from; i < max_edges; i++, count++) { if (rte_strscpy(node->next_nodes[i], next_nodes[count], RTE_NODE_NAMESIZE) < 0) goto restore; } restore: /* Update the linked list to point new node address in prev node */ if (prev) STAILQ_INSERT_AFTER(&node_list, prev, node, next); else STAILQ_INSERT_HEAD(&node_list, node, next); if (need_realloc) node->nb_edges = max_edges; fail: return count; } RTE_EXPORT_SYMBOL(rte_node_edge_shrink) rte_edge_t rte_node_edge_shrink(rte_node_t id, rte_edge_t size) { rte_edge_t rc = RTE_EDGE_ID_INVALID; struct node *node; if (node_from_id(id) == NULL) goto fail; graph_spinlock_lock(); STAILQ_FOREACH(node, &node_list, next) { if (node->id == id) { if (node->nb_edges < size) { rte_errno = E2BIG; } else { node->nb_edges = size; rc = size; } break; } } graph_spinlock_unlock(); fail: return rc; } RTE_EXPORT_SYMBOL(rte_node_edge_update) rte_edge_t rte_node_edge_update(rte_node_t id, rte_edge_t from, const char **next_nodes, uint16_t nb_edges) { rte_edge_t rc = RTE_EDGE_ID_INVALID; struct node *n, *prev; if (node_from_id(id) == NULL) goto fail; graph_spinlock_lock(); prev = NULL; STAILQ_FOREACH(n, &node_list, next) { if (n->id == id) { rc = edge_update(n, prev, from, next_nodes, nb_edges); break; } prev = n; } graph_spinlock_unlock(); fail: return rc; } static rte_node_t node_copy_edges(struct node *node, char *next_nodes[]) { rte_edge_t i; for (i = 0; i < node->nb_edges; i++) next_nodes[i] = node->next_nodes[i]; return i; } RTE_EXPORT_SYMBOL(rte_node_edge_get) rte_node_t rte_node_edge_get(rte_node_t id, char *next_nodes[]) { rte_node_t rc = RTE_NODE_ID_INVALID; struct node *node; if (node_from_id(id) == NULL) goto fail; graph_spinlock_lock(); STAILQ_FOREACH(node, &node_list, next) { if (node->id == id) { if (next_nodes == NULL) rc = sizeof(char *) * node->nb_edges; else rc = node_copy_edges(node, next_nodes); break; } } graph_spinlock_unlock(); fail: return rc; } static void node_scan_dump(FILE *f, rte_node_t id, bool all) { struct node *node; RTE_ASSERT(f != NULL); if (node_from_id(id) == NULL) goto fail; STAILQ_FOREACH(node, &node_list, next) { if (all == true) { node_dump(f, node); } else if (node->id == id) { node_dump(f, node); return; } } fail: return; } RTE_EXPORT_SYMBOL(rte_node_dump) void rte_node_dump(FILE *f, rte_node_t id) { node_scan_dump(f, id, false); } RTE_EXPORT_SYMBOL(rte_node_list_dump) void rte_node_list_dump(FILE *f) { node_scan_dump(f, 0, true); } RTE_EXPORT_SYMBOL(rte_node_max_count) rte_node_t rte_node_max_count(void) { rte_node_t node_id = 0; struct node *node; STAILQ_FOREACH(node, &node_list, next) { if (node_id < node->id) node_id = node->id; } return node_id; } int node_override_process_func(rte_node_t id, rte_node_process_t process) { struct node *node; if (node_from_id(id) == NULL) goto fail; graph_spinlock_lock(); STAILQ_FOREACH(node, &node_list, next) { if (node->id == id) { node->process = process; graph_spinlock_unlock(); return 0; } } graph_spinlock_unlock(); fail: return -1; } RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_free, 25.07) int rte_node_free(rte_node_t id) { struct node *node; int rc = -1; if (node_from_id(id) == NULL) goto fail; graph_spinlock_lock(); STAILQ_FOREACH(node, &node_list, next) { if (id == node->id) { if (!graph_is_node_active_in_graph(node)) { STAILQ_REMOVE(&node_list, node, node, next); free(node); rc = 0; } break; } } graph_spinlock_unlock(); fail: return rc; }