199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(C) 2020 Marvell International Ltd. 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #include <stdbool.h> 699a2dd95SBruce Richardson #include <stdio.h> 772b452c5SDmitry Kozlyuk #include <stdlib.h> 899a2dd95SBruce Richardson #include <string.h> 999a2dd95SBruce Richardson 1099a2dd95SBruce Richardson #include <rte_common.h> 1199a2dd95SBruce Richardson #include <rte_debug.h> 1299a2dd95SBruce Richardson #include <rte_errno.h> 1399a2dd95SBruce Richardson #include <rte_string_fns.h> 1499a2dd95SBruce Richardson 1599a2dd95SBruce Richardson #include "graph_private.h" 1699a2dd95SBruce Richardson 1799a2dd95SBruce Richardson static struct node_head node_list = STAILQ_HEAD_INITIALIZER(node_list); 1899a2dd95SBruce Richardson static rte_node_t node_id; 1999a2dd95SBruce Richardson 2099a2dd95SBruce Richardson #define NODE_ID_CHECK(id) ID_CHECK(id, node_id) 2199a2dd95SBruce Richardson 2299a2dd95SBruce Richardson /* Private functions */ 2399a2dd95SBruce Richardson struct node_head * 2499a2dd95SBruce Richardson node_list_head_get(void) 2599a2dd95SBruce Richardson { 2699a2dd95SBruce Richardson return &node_list; 2799a2dd95SBruce Richardson } 2899a2dd95SBruce Richardson 2999a2dd95SBruce Richardson struct node * 3099a2dd95SBruce Richardson node_from_name(const char *name) 3199a2dd95SBruce Richardson { 3299a2dd95SBruce Richardson struct node *node; 3399a2dd95SBruce Richardson 3499a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) 3599a2dd95SBruce Richardson if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0) 3699a2dd95SBruce Richardson return node; 3799a2dd95SBruce Richardson 3899a2dd95SBruce Richardson return NULL; 3999a2dd95SBruce Richardson } 4099a2dd95SBruce Richardson 4199a2dd95SBruce Richardson static bool 4299a2dd95SBruce Richardson node_has_duplicate_entry(const char *name) 4399a2dd95SBruce Richardson { 4499a2dd95SBruce Richardson struct node *node; 4599a2dd95SBruce Richardson 4699a2dd95SBruce Richardson /* Is duplicate name registered */ 4799a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) { 4899a2dd95SBruce Richardson if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0) { 4999a2dd95SBruce Richardson rte_errno = EEXIST; 5099a2dd95SBruce Richardson return 1; 5199a2dd95SBruce Richardson } 5299a2dd95SBruce Richardson } 5399a2dd95SBruce Richardson return 0; 5499a2dd95SBruce Richardson } 5599a2dd95SBruce Richardson 5699a2dd95SBruce Richardson /* Public functions */ 5799a2dd95SBruce Richardson rte_node_t 5899a2dd95SBruce Richardson __rte_node_register(const struct rte_node_register *reg) 5999a2dd95SBruce Richardson { 6099a2dd95SBruce Richardson struct node *node; 6199a2dd95SBruce Richardson rte_edge_t i; 6299a2dd95SBruce Richardson size_t sz; 6399a2dd95SBruce Richardson 6499a2dd95SBruce Richardson /* Limit Node specific metadata to one cacheline on 64B CL machine */ 6599a2dd95SBruce Richardson RTE_BUILD_BUG_ON((offsetof(struct rte_node, nodes) - 6699a2dd95SBruce Richardson offsetof(struct rte_node, ctx)) != 6799a2dd95SBruce Richardson RTE_CACHE_LINE_MIN_SIZE); 6899a2dd95SBruce Richardson 6999a2dd95SBruce Richardson graph_spinlock_lock(); 7099a2dd95SBruce Richardson 7199a2dd95SBruce Richardson /* Check sanity */ 7299a2dd95SBruce Richardson if (reg == NULL || reg->process == NULL) { 7399a2dd95SBruce Richardson rte_errno = EINVAL; 7499a2dd95SBruce Richardson goto fail; 7599a2dd95SBruce Richardson } 7699a2dd95SBruce Richardson 7799a2dd95SBruce Richardson /* Check for duplicate name */ 7899a2dd95SBruce Richardson if (node_has_duplicate_entry(reg->name)) 7999a2dd95SBruce Richardson goto fail; 8099a2dd95SBruce Richardson 8199a2dd95SBruce Richardson sz = sizeof(struct node) + (reg->nb_edges * RTE_NODE_NAMESIZE); 8299a2dd95SBruce Richardson node = calloc(1, sz); 8399a2dd95SBruce Richardson if (node == NULL) { 8499a2dd95SBruce Richardson rte_errno = ENOMEM; 8599a2dd95SBruce Richardson goto fail; 8699a2dd95SBruce Richardson } 8799a2dd95SBruce Richardson 88070db97eSPavan Nikhilesh if (reg->xstats) { 89070db97eSPavan Nikhilesh sz = sizeof(*reg->xstats) + (reg->xstats->nb_xstats * RTE_NODE_XSTAT_DESC_SIZE); 90070db97eSPavan Nikhilesh node->xstats = calloc(1, sz); 91070db97eSPavan Nikhilesh if (node->xstats == NULL) { 92070db97eSPavan Nikhilesh rte_errno = ENOMEM; 93070db97eSPavan Nikhilesh goto free; 94070db97eSPavan Nikhilesh } 95070db97eSPavan Nikhilesh 96070db97eSPavan Nikhilesh node->xstats->nb_xstats = reg->xstats->nb_xstats; 97070db97eSPavan Nikhilesh for (i = 0; i < reg->xstats->nb_xstats; i++) 98070db97eSPavan Nikhilesh if (rte_strscpy(node->xstats->xstat_desc[i], reg->xstats->xstat_desc[i], 99070db97eSPavan Nikhilesh RTE_NODE_XSTAT_DESC_SIZE) < 0) 100070db97eSPavan Nikhilesh goto free_xstat; 101070db97eSPavan Nikhilesh } 102070db97eSPavan Nikhilesh 10399a2dd95SBruce Richardson /* Initialize the node */ 104dbba7c9eSThomas Monjalon if (rte_strscpy(node->name, reg->name, RTE_NODE_NAMESIZE) < 0) 105070db97eSPavan Nikhilesh goto free_xstat; 10699a2dd95SBruce Richardson node->flags = reg->flags; 10799a2dd95SBruce Richardson node->process = reg->process; 10899a2dd95SBruce Richardson node->init = reg->init; 10999a2dd95SBruce Richardson node->fini = reg->fini; 11099a2dd95SBruce Richardson node->nb_edges = reg->nb_edges; 11199a2dd95SBruce Richardson node->parent_id = reg->parent_id; 11299a2dd95SBruce Richardson for (i = 0; i < reg->nb_edges; i++) { 11399a2dd95SBruce Richardson if (rte_strscpy(node->next_nodes[i], reg->next_nodes[i], 114dbba7c9eSThomas Monjalon RTE_NODE_NAMESIZE) < 0) 115070db97eSPavan Nikhilesh goto free_xstat; 11699a2dd95SBruce Richardson } 11799a2dd95SBruce Richardson 1181d08f290SZhirun Yan node->lcore_id = RTE_MAX_LCORE; 11999a2dd95SBruce Richardson node->id = node_id++; 12099a2dd95SBruce Richardson 12199a2dd95SBruce Richardson /* Add the node at tail */ 12299a2dd95SBruce Richardson STAILQ_INSERT_TAIL(&node_list, node, next); 12399a2dd95SBruce Richardson graph_spinlock_unlock(); 12499a2dd95SBruce Richardson 12599a2dd95SBruce Richardson return node->id; 126070db97eSPavan Nikhilesh free_xstat: 127070db97eSPavan Nikhilesh free(node->xstats); 12899a2dd95SBruce Richardson free: 12999a2dd95SBruce Richardson free(node); 13099a2dd95SBruce Richardson fail: 13199a2dd95SBruce Richardson graph_spinlock_unlock(); 13299a2dd95SBruce Richardson return RTE_NODE_ID_INVALID; 13399a2dd95SBruce Richardson } 13499a2dd95SBruce Richardson 13599a2dd95SBruce Richardson static rte_node_t 13699a2dd95SBruce Richardson node_clone(struct node *node, const char *name) 13799a2dd95SBruce Richardson { 13899a2dd95SBruce Richardson rte_node_t rc = RTE_NODE_ID_INVALID; 13999a2dd95SBruce Richardson struct rte_node_register *reg; 14099a2dd95SBruce Richardson rte_edge_t i; 14199a2dd95SBruce Richardson 14299a2dd95SBruce Richardson /* Don't allow to clone a node from a cloned node */ 14399a2dd95SBruce Richardson if (node->parent_id != RTE_NODE_ID_INVALID) { 14499a2dd95SBruce Richardson rte_errno = EEXIST; 14599a2dd95SBruce Richardson goto fail; 14699a2dd95SBruce Richardson } 14799a2dd95SBruce Richardson 14899a2dd95SBruce Richardson reg = calloc(1, sizeof(*reg) + (sizeof(char *) * node->nb_edges)); 14999a2dd95SBruce Richardson if (reg == NULL) { 15099a2dd95SBruce Richardson rte_errno = ENOMEM; 15199a2dd95SBruce Richardson goto fail; 15299a2dd95SBruce Richardson } 15399a2dd95SBruce Richardson 154070db97eSPavan Nikhilesh if (node->xstats) { 155070db97eSPavan Nikhilesh reg->xstats = calloc(1, sizeof(*node->xstats) + 156070db97eSPavan Nikhilesh (node->xstats->nb_xstats * RTE_NODE_XSTAT_DESC_SIZE)); 157070db97eSPavan Nikhilesh if (reg->xstats == NULL) { 158070db97eSPavan Nikhilesh rte_errno = ENOMEM; 159*5e65cd4aSPavan Nikhilesh goto free; 160070db97eSPavan Nikhilesh } 161070db97eSPavan Nikhilesh 162070db97eSPavan Nikhilesh for (i = 0; i < node->xstats->nb_xstats; i++) 163070db97eSPavan Nikhilesh if (rte_strscpy(reg->xstats->xstat_desc[i], node->xstats->xstat_desc[i], 164070db97eSPavan Nikhilesh RTE_NODE_XSTAT_DESC_SIZE) < 0) 165070db97eSPavan Nikhilesh goto free_xstat; 166070db97eSPavan Nikhilesh } 167070db97eSPavan Nikhilesh 16899a2dd95SBruce Richardson /* Clone the source node */ 16999a2dd95SBruce Richardson reg->flags = node->flags; 17099a2dd95SBruce Richardson reg->process = node->process; 17199a2dd95SBruce Richardson reg->init = node->init; 17299a2dd95SBruce Richardson reg->fini = node->fini; 17399a2dd95SBruce Richardson reg->nb_edges = node->nb_edges; 17499a2dd95SBruce Richardson reg->parent_id = node->id; 17599a2dd95SBruce Richardson 17699a2dd95SBruce Richardson for (i = 0; i < node->nb_edges; i++) 17799a2dd95SBruce Richardson reg->next_nodes[i] = node->next_nodes[i]; 17899a2dd95SBruce Richardson 17999a2dd95SBruce Richardson /* Naming ceremony of the new node. name is node->name + "-" + name */ 180b6ef3794SZhirun Yan if (clone_name(reg->name, node->name, name)) 181*5e65cd4aSPavan Nikhilesh goto free_xstat; 18299a2dd95SBruce Richardson 18399a2dd95SBruce Richardson rc = __rte_node_register(reg); 184070db97eSPavan Nikhilesh free_xstat: 185070db97eSPavan Nikhilesh free(reg->xstats); 18699a2dd95SBruce Richardson free: 18799a2dd95SBruce Richardson free(reg); 18899a2dd95SBruce Richardson fail: 18999a2dd95SBruce Richardson return rc; 19099a2dd95SBruce Richardson } 19199a2dd95SBruce Richardson 19299a2dd95SBruce Richardson rte_node_t 19399a2dd95SBruce Richardson rte_node_clone(rte_node_t id, const char *name) 19499a2dd95SBruce Richardson { 19599a2dd95SBruce Richardson struct node *node; 19699a2dd95SBruce Richardson 19799a2dd95SBruce Richardson NODE_ID_CHECK(id); 19899a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) 19999a2dd95SBruce Richardson if (node->id == id) 20099a2dd95SBruce Richardson return node_clone(node, name); 20199a2dd95SBruce Richardson 20299a2dd95SBruce Richardson fail: 20399a2dd95SBruce Richardson return RTE_NODE_ID_INVALID; 20499a2dd95SBruce Richardson } 20599a2dd95SBruce Richardson 20699a2dd95SBruce Richardson rte_node_t 20799a2dd95SBruce Richardson rte_node_from_name(const char *name) 20899a2dd95SBruce Richardson { 20999a2dd95SBruce Richardson struct node *node; 21099a2dd95SBruce Richardson 21199a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) 21299a2dd95SBruce Richardson if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0) 21399a2dd95SBruce Richardson return node->id; 21499a2dd95SBruce Richardson 21599a2dd95SBruce Richardson return RTE_NODE_ID_INVALID; 21699a2dd95SBruce Richardson } 21799a2dd95SBruce Richardson 21899a2dd95SBruce Richardson char * 21999a2dd95SBruce Richardson rte_node_id_to_name(rte_node_t id) 22099a2dd95SBruce Richardson { 22199a2dd95SBruce Richardson struct node *node; 22299a2dd95SBruce Richardson 22399a2dd95SBruce Richardson NODE_ID_CHECK(id); 22499a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) 22599a2dd95SBruce Richardson if (node->id == id) 22699a2dd95SBruce Richardson return node->name; 22799a2dd95SBruce Richardson 22899a2dd95SBruce Richardson fail: 22999a2dd95SBruce Richardson return NULL; 23099a2dd95SBruce Richardson } 23199a2dd95SBruce Richardson 23299a2dd95SBruce Richardson rte_edge_t 23399a2dd95SBruce Richardson rte_node_edge_count(rte_node_t id) 23499a2dd95SBruce Richardson { 23599a2dd95SBruce Richardson struct node *node; 23699a2dd95SBruce Richardson 23799a2dd95SBruce Richardson NODE_ID_CHECK(id); 23899a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) 23999a2dd95SBruce Richardson if (node->id == id) 24099a2dd95SBruce Richardson return node->nb_edges; 24199a2dd95SBruce Richardson fail: 24299a2dd95SBruce Richardson return RTE_EDGE_ID_INVALID; 24399a2dd95SBruce Richardson } 24499a2dd95SBruce Richardson 24599a2dd95SBruce Richardson static rte_edge_t 24699a2dd95SBruce Richardson edge_update(struct node *node, struct node *prev, rte_edge_t from, 24799a2dd95SBruce Richardson const char **next_nodes, rte_edge_t nb_edges) 24899a2dd95SBruce Richardson { 24999a2dd95SBruce Richardson rte_edge_t i, max_edges, count = 0; 25099a2dd95SBruce Richardson struct node *new_node; 25199a2dd95SBruce Richardson bool need_realloc; 25299a2dd95SBruce Richardson size_t sz; 25399a2dd95SBruce Richardson 25499a2dd95SBruce Richardson if (from == RTE_EDGE_ID_INVALID) 25599a2dd95SBruce Richardson from = node->nb_edges; 25699a2dd95SBruce Richardson 25799a2dd95SBruce Richardson /* Don't create hole in next_nodes[] list */ 25899a2dd95SBruce Richardson if (from > node->nb_edges) { 25999a2dd95SBruce Richardson rte_errno = ENOMEM; 26099a2dd95SBruce Richardson goto fail; 26199a2dd95SBruce Richardson } 26299a2dd95SBruce Richardson 26399a2dd95SBruce Richardson /* Remove me from list */ 26499a2dd95SBruce Richardson STAILQ_REMOVE(&node_list, node, node, next); 26599a2dd95SBruce Richardson 26699a2dd95SBruce Richardson /* Allocate the storage space for new node if required */ 26799a2dd95SBruce Richardson max_edges = from + nb_edges; 26899a2dd95SBruce Richardson need_realloc = max_edges > node->nb_edges; 26999a2dd95SBruce Richardson if (need_realloc) { 27099a2dd95SBruce Richardson sz = sizeof(struct node) + (max_edges * RTE_NODE_NAMESIZE); 27199a2dd95SBruce Richardson new_node = realloc(node, sz); 27299a2dd95SBruce Richardson if (new_node == NULL) { 27399a2dd95SBruce Richardson rte_errno = ENOMEM; 27499a2dd95SBruce Richardson goto restore; 27599a2dd95SBruce Richardson } else { 27699a2dd95SBruce Richardson node = new_node; 27799a2dd95SBruce Richardson } 27899a2dd95SBruce Richardson } 27999a2dd95SBruce Richardson 28099a2dd95SBruce Richardson /* Update the new nodes name */ 28199a2dd95SBruce Richardson for (i = from; i < max_edges; i++, count++) { 28299a2dd95SBruce Richardson if (rte_strscpy(node->next_nodes[i], next_nodes[count], 283dbba7c9eSThomas Monjalon RTE_NODE_NAMESIZE) < 0) 28499a2dd95SBruce Richardson goto restore; 28599a2dd95SBruce Richardson } 28699a2dd95SBruce Richardson restore: 28799a2dd95SBruce Richardson /* Update the linked list to point new node address in prev node */ 28899a2dd95SBruce Richardson if (prev) 28999a2dd95SBruce Richardson STAILQ_INSERT_AFTER(&node_list, prev, node, next); 29099a2dd95SBruce Richardson else 29199a2dd95SBruce Richardson STAILQ_INSERT_HEAD(&node_list, node, next); 29299a2dd95SBruce Richardson 29399a2dd95SBruce Richardson if (need_realloc) 29499a2dd95SBruce Richardson node->nb_edges = max_edges; 29599a2dd95SBruce Richardson 29699a2dd95SBruce Richardson fail: 29799a2dd95SBruce Richardson return count; 29899a2dd95SBruce Richardson } 29999a2dd95SBruce Richardson 30099a2dd95SBruce Richardson rte_edge_t 30199a2dd95SBruce Richardson rte_node_edge_shrink(rte_node_t id, rte_edge_t size) 30299a2dd95SBruce Richardson { 30399a2dd95SBruce Richardson rte_edge_t rc = RTE_EDGE_ID_INVALID; 30499a2dd95SBruce Richardson struct node *node; 30599a2dd95SBruce Richardson 30699a2dd95SBruce Richardson NODE_ID_CHECK(id); 30799a2dd95SBruce Richardson graph_spinlock_lock(); 30899a2dd95SBruce Richardson 30999a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) { 31099a2dd95SBruce Richardson if (node->id == id) { 31199a2dd95SBruce Richardson if (node->nb_edges < size) { 31299a2dd95SBruce Richardson rte_errno = E2BIG; 31399cc0a9aSDavid Marchand } else { 31499a2dd95SBruce Richardson node->nb_edges = size; 31599a2dd95SBruce Richardson rc = size; 31699cc0a9aSDavid Marchand } 31799a2dd95SBruce Richardson break; 31899a2dd95SBruce Richardson } 31999a2dd95SBruce Richardson } 32099a2dd95SBruce Richardson 32199a2dd95SBruce Richardson graph_spinlock_unlock(); 32299cc0a9aSDavid Marchand fail: 32399a2dd95SBruce Richardson return rc; 32499a2dd95SBruce Richardson } 32599a2dd95SBruce Richardson 32699a2dd95SBruce Richardson rte_edge_t 32799a2dd95SBruce Richardson rte_node_edge_update(rte_node_t id, rte_edge_t from, const char **next_nodes, 32899a2dd95SBruce Richardson uint16_t nb_edges) 32999a2dd95SBruce Richardson { 33099a2dd95SBruce Richardson rte_edge_t rc = RTE_EDGE_ID_INVALID; 33199a2dd95SBruce Richardson struct node *n, *prev; 33299a2dd95SBruce Richardson 33399a2dd95SBruce Richardson NODE_ID_CHECK(id); 33499a2dd95SBruce Richardson graph_spinlock_lock(); 33599a2dd95SBruce Richardson 33699a2dd95SBruce Richardson prev = NULL; 33799a2dd95SBruce Richardson STAILQ_FOREACH(n, &node_list, next) { 33899a2dd95SBruce Richardson if (n->id == id) { 33999a2dd95SBruce Richardson rc = edge_update(n, prev, from, next_nodes, nb_edges); 34099a2dd95SBruce Richardson break; 34199a2dd95SBruce Richardson } 34299a2dd95SBruce Richardson prev = n; 34399a2dd95SBruce Richardson } 34499a2dd95SBruce Richardson 34599a2dd95SBruce Richardson graph_spinlock_unlock(); 34699a2dd95SBruce Richardson fail: 34799a2dd95SBruce Richardson return rc; 34899a2dd95SBruce Richardson } 34999a2dd95SBruce Richardson 35099a2dd95SBruce Richardson static rte_node_t 35199a2dd95SBruce Richardson node_copy_edges(struct node *node, char *next_nodes[]) 35299a2dd95SBruce Richardson { 35399a2dd95SBruce Richardson rte_edge_t i; 35499a2dd95SBruce Richardson 35599a2dd95SBruce Richardson for (i = 0; i < node->nb_edges; i++) 35699a2dd95SBruce Richardson next_nodes[i] = node->next_nodes[i]; 35799a2dd95SBruce Richardson 35899a2dd95SBruce Richardson return i; 35999a2dd95SBruce Richardson } 36099a2dd95SBruce Richardson 36199a2dd95SBruce Richardson rte_node_t 36299a2dd95SBruce Richardson rte_node_edge_get(rte_node_t id, char *next_nodes[]) 36399a2dd95SBruce Richardson { 36499a2dd95SBruce Richardson rte_node_t rc = RTE_NODE_ID_INVALID; 36599a2dd95SBruce Richardson struct node *node; 36699a2dd95SBruce Richardson 36799a2dd95SBruce Richardson NODE_ID_CHECK(id); 36899a2dd95SBruce Richardson graph_spinlock_lock(); 36999a2dd95SBruce Richardson 37099a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) { 37199a2dd95SBruce Richardson if (node->id == id) { 37299a2dd95SBruce Richardson if (next_nodes == NULL) 37399a2dd95SBruce Richardson rc = sizeof(char *) * node->nb_edges; 37499a2dd95SBruce Richardson else 37599a2dd95SBruce Richardson rc = node_copy_edges(node, next_nodes); 37699a2dd95SBruce Richardson break; 37799a2dd95SBruce Richardson } 37899a2dd95SBruce Richardson } 37999a2dd95SBruce Richardson 38099a2dd95SBruce Richardson graph_spinlock_unlock(); 38199a2dd95SBruce Richardson fail: 38299a2dd95SBruce Richardson return rc; 38399a2dd95SBruce Richardson } 38499a2dd95SBruce Richardson 38599a2dd95SBruce Richardson static void 38699a2dd95SBruce Richardson node_scan_dump(FILE *f, rte_node_t id, bool all) 38799a2dd95SBruce Richardson { 38899a2dd95SBruce Richardson struct node *node; 38999a2dd95SBruce Richardson 39099a2dd95SBruce Richardson RTE_ASSERT(f != NULL); 39199a2dd95SBruce Richardson NODE_ID_CHECK(id); 39299a2dd95SBruce Richardson 39399a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) { 39499a2dd95SBruce Richardson if (all == true) { 39599a2dd95SBruce Richardson node_dump(f, node); 39699a2dd95SBruce Richardson } else if (node->id == id) { 39799a2dd95SBruce Richardson node_dump(f, node); 39899a2dd95SBruce Richardson return; 39999a2dd95SBruce Richardson } 40099a2dd95SBruce Richardson } 40199a2dd95SBruce Richardson fail: 40299a2dd95SBruce Richardson return; 40399a2dd95SBruce Richardson } 40499a2dd95SBruce Richardson 40599a2dd95SBruce Richardson void 40699a2dd95SBruce Richardson rte_node_dump(FILE *f, rte_node_t id) 40799a2dd95SBruce Richardson { 40899a2dd95SBruce Richardson node_scan_dump(f, id, false); 40999a2dd95SBruce Richardson } 41099a2dd95SBruce Richardson 41199a2dd95SBruce Richardson void 41299a2dd95SBruce Richardson rte_node_list_dump(FILE *f) 41399a2dd95SBruce Richardson { 41499a2dd95SBruce Richardson node_scan_dump(f, 0, true); 41599a2dd95SBruce Richardson } 41699a2dd95SBruce Richardson 41799a2dd95SBruce Richardson rte_node_t 41899a2dd95SBruce Richardson rte_node_max_count(void) 41999a2dd95SBruce Richardson { 42099a2dd95SBruce Richardson return node_id; 42199a2dd95SBruce Richardson } 422