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>
799a2dd95SBruce Richardson #include <string.h>
899a2dd95SBruce Richardson
999a2dd95SBruce Richardson #include <rte_common.h>
1099a2dd95SBruce Richardson #include <rte_debug.h>
1199a2dd95SBruce Richardson #include <rte_errno.h>
1299a2dd95SBruce Richardson #include <rte_string_fns.h>
1399a2dd95SBruce Richardson
1499a2dd95SBruce Richardson #include "graph_private.h"
1599a2dd95SBruce Richardson
1699a2dd95SBruce Richardson static struct node_head node_list = STAILQ_HEAD_INITIALIZER(node_list);
1799a2dd95SBruce Richardson static rte_node_t node_id;
1899a2dd95SBruce Richardson
1999a2dd95SBruce Richardson #define NODE_ID_CHECK(id) ID_CHECK(id, node_id)
2099a2dd95SBruce Richardson
2199a2dd95SBruce Richardson /* Private functions */
2299a2dd95SBruce Richardson struct node_head *
node_list_head_get(void)2399a2dd95SBruce Richardson node_list_head_get(void)
2499a2dd95SBruce Richardson {
2599a2dd95SBruce Richardson return &node_list;
2699a2dd95SBruce Richardson }
2799a2dd95SBruce Richardson
2899a2dd95SBruce Richardson struct node *
node_from_name(const char * name)2999a2dd95SBruce Richardson node_from_name(const char *name)
3099a2dd95SBruce Richardson {
3199a2dd95SBruce Richardson struct node *node;
3299a2dd95SBruce Richardson
3399a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next)
3499a2dd95SBruce Richardson if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0)
3599a2dd95SBruce Richardson return node;
3699a2dd95SBruce Richardson
3799a2dd95SBruce Richardson return NULL;
3899a2dd95SBruce Richardson }
3999a2dd95SBruce Richardson
4099a2dd95SBruce Richardson static bool
node_has_duplicate_entry(const char * name)4199a2dd95SBruce Richardson node_has_duplicate_entry(const char *name)
4299a2dd95SBruce Richardson {
4399a2dd95SBruce Richardson struct node *node;
4499a2dd95SBruce Richardson
4599a2dd95SBruce Richardson /* Is duplicate name registered */
4699a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) {
4799a2dd95SBruce Richardson if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0) {
4899a2dd95SBruce Richardson rte_errno = EEXIST;
4999a2dd95SBruce Richardson return 1;
5099a2dd95SBruce Richardson }
5199a2dd95SBruce Richardson }
5299a2dd95SBruce Richardson return 0;
5399a2dd95SBruce Richardson }
5499a2dd95SBruce Richardson
5599a2dd95SBruce Richardson /* Public functions */
5699a2dd95SBruce Richardson rte_node_t
__rte_node_register(const struct rte_node_register * reg)5799a2dd95SBruce Richardson __rte_node_register(const struct rte_node_register *reg)
5899a2dd95SBruce Richardson {
5999a2dd95SBruce Richardson struct node *node;
6099a2dd95SBruce Richardson rte_edge_t i;
6199a2dd95SBruce Richardson size_t sz;
6299a2dd95SBruce Richardson
6399a2dd95SBruce Richardson /* Limit Node specific metadata to one cacheline on 64B CL machine */
6499a2dd95SBruce Richardson RTE_BUILD_BUG_ON((offsetof(struct rte_node, nodes) -
6599a2dd95SBruce Richardson offsetof(struct rte_node, ctx)) !=
6699a2dd95SBruce Richardson RTE_CACHE_LINE_MIN_SIZE);
6799a2dd95SBruce Richardson
6899a2dd95SBruce Richardson graph_spinlock_lock();
6999a2dd95SBruce Richardson
7099a2dd95SBruce Richardson /* Check sanity */
7199a2dd95SBruce Richardson if (reg == NULL || reg->process == NULL) {
7299a2dd95SBruce Richardson rte_errno = EINVAL;
7399a2dd95SBruce Richardson goto fail;
7499a2dd95SBruce Richardson }
7599a2dd95SBruce Richardson
7699a2dd95SBruce Richardson /* Check for duplicate name */
7799a2dd95SBruce Richardson if (node_has_duplicate_entry(reg->name))
7899a2dd95SBruce Richardson goto fail;
7999a2dd95SBruce Richardson
8099a2dd95SBruce Richardson sz = sizeof(struct node) + (reg->nb_edges * RTE_NODE_NAMESIZE);
8199a2dd95SBruce Richardson node = calloc(1, sz);
8299a2dd95SBruce Richardson if (node == NULL) {
8399a2dd95SBruce Richardson rte_errno = ENOMEM;
8499a2dd95SBruce Richardson goto fail;
8599a2dd95SBruce Richardson }
8699a2dd95SBruce Richardson
8799a2dd95SBruce Richardson /* Initialize the node */
88*dbba7c9eSThomas Monjalon if (rte_strscpy(node->name, reg->name, RTE_NODE_NAMESIZE) < 0)
8999a2dd95SBruce Richardson goto free;
9099a2dd95SBruce Richardson node->flags = reg->flags;
9199a2dd95SBruce Richardson node->process = reg->process;
9299a2dd95SBruce Richardson node->init = reg->init;
9399a2dd95SBruce Richardson node->fini = reg->fini;
9499a2dd95SBruce Richardson node->nb_edges = reg->nb_edges;
9599a2dd95SBruce Richardson node->parent_id = reg->parent_id;
9699a2dd95SBruce Richardson for (i = 0; i < reg->nb_edges; i++) {
9799a2dd95SBruce Richardson if (rte_strscpy(node->next_nodes[i], reg->next_nodes[i],
98*dbba7c9eSThomas Monjalon RTE_NODE_NAMESIZE) < 0)
9999a2dd95SBruce Richardson goto free;
10099a2dd95SBruce Richardson }
10199a2dd95SBruce Richardson
10299a2dd95SBruce Richardson node->id = node_id++;
10399a2dd95SBruce Richardson
10499a2dd95SBruce Richardson /* Add the node at tail */
10599a2dd95SBruce Richardson STAILQ_INSERT_TAIL(&node_list, node, next);
10699a2dd95SBruce Richardson graph_spinlock_unlock();
10799a2dd95SBruce Richardson
10899a2dd95SBruce Richardson return node->id;
10999a2dd95SBruce Richardson free:
11099a2dd95SBruce Richardson free(node);
11199a2dd95SBruce Richardson fail:
11299a2dd95SBruce Richardson graph_spinlock_unlock();
11399a2dd95SBruce Richardson return RTE_NODE_ID_INVALID;
11499a2dd95SBruce Richardson }
11599a2dd95SBruce Richardson
11699a2dd95SBruce Richardson static int
clone_name(struct rte_node_register * reg,struct node * node,const char * name)11799a2dd95SBruce Richardson clone_name(struct rte_node_register *reg, struct node *node, const char *name)
11899a2dd95SBruce Richardson {
11999a2dd95SBruce Richardson ssize_t sz, rc;
12099a2dd95SBruce Richardson
12199a2dd95SBruce Richardson #define SZ RTE_NODE_NAMESIZE
12299a2dd95SBruce Richardson rc = rte_strscpy(reg->name, node->name, SZ);
12399a2dd95SBruce Richardson if (rc < 0)
12499a2dd95SBruce Richardson goto fail;
12599a2dd95SBruce Richardson sz = rc;
12699a2dd95SBruce Richardson rc = rte_strscpy(reg->name + sz, "-", RTE_MAX((int16_t)(SZ - sz), 0));
12799a2dd95SBruce Richardson if (rc < 0)
12899a2dd95SBruce Richardson goto fail;
12999a2dd95SBruce Richardson sz += rc;
13099a2dd95SBruce Richardson sz = rte_strscpy(reg->name + sz, name, RTE_MAX((int16_t)(SZ - sz), 0));
13199a2dd95SBruce Richardson if (sz < 0)
13299a2dd95SBruce Richardson goto fail;
13399a2dd95SBruce Richardson
13499a2dd95SBruce Richardson return 0;
13599a2dd95SBruce Richardson fail:
13699a2dd95SBruce Richardson rte_errno = E2BIG;
13799a2dd95SBruce Richardson return -rte_errno;
13899a2dd95SBruce Richardson }
13999a2dd95SBruce Richardson
14099a2dd95SBruce Richardson static rte_node_t
node_clone(struct node * node,const char * name)14199a2dd95SBruce Richardson node_clone(struct node *node, const char *name)
14299a2dd95SBruce Richardson {
14399a2dd95SBruce Richardson rte_node_t rc = RTE_NODE_ID_INVALID;
14499a2dd95SBruce Richardson struct rte_node_register *reg;
14599a2dd95SBruce Richardson rte_edge_t i;
14699a2dd95SBruce Richardson
14799a2dd95SBruce Richardson /* Don't allow to clone a node from a cloned node */
14899a2dd95SBruce Richardson if (node->parent_id != RTE_NODE_ID_INVALID) {
14999a2dd95SBruce Richardson rte_errno = EEXIST;
15099a2dd95SBruce Richardson goto fail;
15199a2dd95SBruce Richardson }
15299a2dd95SBruce Richardson
15399a2dd95SBruce Richardson reg = calloc(1, sizeof(*reg) + (sizeof(char *) * node->nb_edges));
15499a2dd95SBruce Richardson if (reg == NULL) {
15599a2dd95SBruce Richardson rte_errno = ENOMEM;
15699a2dd95SBruce Richardson goto fail;
15799a2dd95SBruce Richardson }
15899a2dd95SBruce Richardson
15999a2dd95SBruce Richardson /* Clone the source node */
16099a2dd95SBruce Richardson reg->flags = node->flags;
16199a2dd95SBruce Richardson reg->process = node->process;
16299a2dd95SBruce Richardson reg->init = node->init;
16399a2dd95SBruce Richardson reg->fini = node->fini;
16499a2dd95SBruce Richardson reg->nb_edges = node->nb_edges;
16599a2dd95SBruce Richardson reg->parent_id = node->id;
16699a2dd95SBruce Richardson
16799a2dd95SBruce Richardson for (i = 0; i < node->nb_edges; i++)
16899a2dd95SBruce Richardson reg->next_nodes[i] = node->next_nodes[i];
16999a2dd95SBruce Richardson
17099a2dd95SBruce Richardson /* Naming ceremony of the new node. name is node->name + "-" + name */
17199a2dd95SBruce Richardson if (clone_name(reg, node, name))
17299a2dd95SBruce Richardson goto free;
17399a2dd95SBruce Richardson
17499a2dd95SBruce Richardson rc = __rte_node_register(reg);
17599a2dd95SBruce Richardson free:
17699a2dd95SBruce Richardson free(reg);
17799a2dd95SBruce Richardson fail:
17899a2dd95SBruce Richardson return rc;
17999a2dd95SBruce Richardson }
18099a2dd95SBruce Richardson
18199a2dd95SBruce Richardson rte_node_t
rte_node_clone(rte_node_t id,const char * name)18299a2dd95SBruce Richardson rte_node_clone(rte_node_t id, const char *name)
18399a2dd95SBruce Richardson {
18499a2dd95SBruce Richardson struct node *node;
18599a2dd95SBruce Richardson
18699a2dd95SBruce Richardson NODE_ID_CHECK(id);
18799a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next)
18899a2dd95SBruce Richardson if (node->id == id)
18999a2dd95SBruce Richardson return node_clone(node, name);
19099a2dd95SBruce Richardson
19199a2dd95SBruce Richardson fail:
19299a2dd95SBruce Richardson return RTE_NODE_ID_INVALID;
19399a2dd95SBruce Richardson }
19499a2dd95SBruce Richardson
19599a2dd95SBruce Richardson rte_node_t
rte_node_from_name(const char * name)19699a2dd95SBruce Richardson rte_node_from_name(const char *name)
19799a2dd95SBruce Richardson {
19899a2dd95SBruce Richardson struct node *node;
19999a2dd95SBruce Richardson
20099a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next)
20199a2dd95SBruce Richardson if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0)
20299a2dd95SBruce Richardson return node->id;
20399a2dd95SBruce Richardson
20499a2dd95SBruce Richardson return RTE_NODE_ID_INVALID;
20599a2dd95SBruce Richardson }
20699a2dd95SBruce Richardson
20799a2dd95SBruce Richardson char *
rte_node_id_to_name(rte_node_t id)20899a2dd95SBruce Richardson rte_node_id_to_name(rte_node_t id)
20999a2dd95SBruce Richardson {
21099a2dd95SBruce Richardson struct node *node;
21199a2dd95SBruce Richardson
21299a2dd95SBruce Richardson NODE_ID_CHECK(id);
21399a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next)
21499a2dd95SBruce Richardson if (node->id == id)
21599a2dd95SBruce Richardson return node->name;
21699a2dd95SBruce Richardson
21799a2dd95SBruce Richardson fail:
21899a2dd95SBruce Richardson return NULL;
21999a2dd95SBruce Richardson }
22099a2dd95SBruce Richardson
22199a2dd95SBruce Richardson rte_edge_t
rte_node_edge_count(rte_node_t id)22299a2dd95SBruce Richardson rte_node_edge_count(rte_node_t id)
22399a2dd95SBruce Richardson {
22499a2dd95SBruce Richardson struct node *node;
22599a2dd95SBruce Richardson
22699a2dd95SBruce Richardson NODE_ID_CHECK(id);
22799a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next)
22899a2dd95SBruce Richardson if (node->id == id)
22999a2dd95SBruce Richardson return node->nb_edges;
23099a2dd95SBruce Richardson fail:
23199a2dd95SBruce Richardson return RTE_EDGE_ID_INVALID;
23299a2dd95SBruce Richardson }
23399a2dd95SBruce Richardson
23499a2dd95SBruce Richardson 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)23599a2dd95SBruce Richardson edge_update(struct node *node, struct node *prev, rte_edge_t from,
23699a2dd95SBruce Richardson const char **next_nodes, rte_edge_t nb_edges)
23799a2dd95SBruce Richardson {
23899a2dd95SBruce Richardson rte_edge_t i, max_edges, count = 0;
23999a2dd95SBruce Richardson struct node *new_node;
24099a2dd95SBruce Richardson bool need_realloc;
24199a2dd95SBruce Richardson size_t sz;
24299a2dd95SBruce Richardson
24399a2dd95SBruce Richardson if (from == RTE_EDGE_ID_INVALID)
24499a2dd95SBruce Richardson from = node->nb_edges;
24599a2dd95SBruce Richardson
24699a2dd95SBruce Richardson /* Don't create hole in next_nodes[] list */
24799a2dd95SBruce Richardson if (from > node->nb_edges) {
24899a2dd95SBruce Richardson rte_errno = ENOMEM;
24999a2dd95SBruce Richardson goto fail;
25099a2dd95SBruce Richardson }
25199a2dd95SBruce Richardson
25299a2dd95SBruce Richardson /* Remove me from list */
25399a2dd95SBruce Richardson STAILQ_REMOVE(&node_list, node, node, next);
25499a2dd95SBruce Richardson
25599a2dd95SBruce Richardson /* Allocate the storage space for new node if required */
25699a2dd95SBruce Richardson max_edges = from + nb_edges;
25799a2dd95SBruce Richardson need_realloc = max_edges > node->nb_edges;
25899a2dd95SBruce Richardson if (need_realloc) {
25999a2dd95SBruce Richardson sz = sizeof(struct node) + (max_edges * RTE_NODE_NAMESIZE);
26099a2dd95SBruce Richardson new_node = realloc(node, sz);
26199a2dd95SBruce Richardson if (new_node == NULL) {
26299a2dd95SBruce Richardson rte_errno = ENOMEM;
26399a2dd95SBruce Richardson goto restore;
26499a2dd95SBruce Richardson } else {
26599a2dd95SBruce Richardson node = new_node;
26699a2dd95SBruce Richardson }
26799a2dd95SBruce Richardson }
26899a2dd95SBruce Richardson
26999a2dd95SBruce Richardson /* Update the new nodes name */
27099a2dd95SBruce Richardson for (i = from; i < max_edges; i++, count++) {
27199a2dd95SBruce Richardson if (rte_strscpy(node->next_nodes[i], next_nodes[count],
272*dbba7c9eSThomas Monjalon RTE_NODE_NAMESIZE) < 0)
27399a2dd95SBruce Richardson goto restore;
27499a2dd95SBruce Richardson }
27599a2dd95SBruce Richardson restore:
27699a2dd95SBruce Richardson /* Update the linked list to point new node address in prev node */
27799a2dd95SBruce Richardson if (prev)
27899a2dd95SBruce Richardson STAILQ_INSERT_AFTER(&node_list, prev, node, next);
27999a2dd95SBruce Richardson else
28099a2dd95SBruce Richardson STAILQ_INSERT_HEAD(&node_list, node, next);
28199a2dd95SBruce Richardson
28299a2dd95SBruce Richardson if (need_realloc)
28399a2dd95SBruce Richardson node->nb_edges = max_edges;
28499a2dd95SBruce Richardson
28599a2dd95SBruce Richardson fail:
28699a2dd95SBruce Richardson return count;
28799a2dd95SBruce Richardson }
28899a2dd95SBruce Richardson
28999a2dd95SBruce Richardson rte_edge_t
rte_node_edge_shrink(rte_node_t id,rte_edge_t size)29099a2dd95SBruce Richardson rte_node_edge_shrink(rte_node_t id, rte_edge_t size)
29199a2dd95SBruce Richardson {
29299a2dd95SBruce Richardson rte_edge_t rc = RTE_EDGE_ID_INVALID;
29399a2dd95SBruce Richardson struct node *node;
29499a2dd95SBruce Richardson
29599a2dd95SBruce Richardson NODE_ID_CHECK(id);
29699a2dd95SBruce Richardson graph_spinlock_lock();
29799a2dd95SBruce Richardson
29899a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) {
29999a2dd95SBruce Richardson if (node->id == id) {
30099a2dd95SBruce Richardson if (node->nb_edges < size) {
30199a2dd95SBruce Richardson rte_errno = E2BIG;
30299a2dd95SBruce Richardson goto fail;
30399a2dd95SBruce Richardson }
30499a2dd95SBruce Richardson node->nb_edges = size;
30599a2dd95SBruce Richardson rc = size;
30699a2dd95SBruce Richardson break;
30799a2dd95SBruce Richardson }
30899a2dd95SBruce Richardson }
30999a2dd95SBruce Richardson
31099a2dd95SBruce Richardson fail:
31199a2dd95SBruce Richardson graph_spinlock_unlock();
31299a2dd95SBruce Richardson return rc;
31399a2dd95SBruce Richardson }
31499a2dd95SBruce Richardson
31599a2dd95SBruce Richardson rte_edge_t
rte_node_edge_update(rte_node_t id,rte_edge_t from,const char ** next_nodes,uint16_t nb_edges)31699a2dd95SBruce Richardson rte_node_edge_update(rte_node_t id, rte_edge_t from, const char **next_nodes,
31799a2dd95SBruce Richardson uint16_t nb_edges)
31899a2dd95SBruce Richardson {
31999a2dd95SBruce Richardson rte_edge_t rc = RTE_EDGE_ID_INVALID;
32099a2dd95SBruce Richardson struct node *n, *prev;
32199a2dd95SBruce Richardson
32299a2dd95SBruce Richardson NODE_ID_CHECK(id);
32399a2dd95SBruce Richardson graph_spinlock_lock();
32499a2dd95SBruce Richardson
32599a2dd95SBruce Richardson prev = NULL;
32699a2dd95SBruce Richardson STAILQ_FOREACH(n, &node_list, next) {
32799a2dd95SBruce Richardson if (n->id == id) {
32899a2dd95SBruce Richardson rc = edge_update(n, prev, from, next_nodes, nb_edges);
32999a2dd95SBruce Richardson break;
33099a2dd95SBruce Richardson }
33199a2dd95SBruce Richardson prev = n;
33299a2dd95SBruce Richardson }
33399a2dd95SBruce Richardson
33499a2dd95SBruce Richardson graph_spinlock_unlock();
33599a2dd95SBruce Richardson fail:
33699a2dd95SBruce Richardson return rc;
33799a2dd95SBruce Richardson }
33899a2dd95SBruce Richardson
33999a2dd95SBruce Richardson static rte_node_t
node_copy_edges(struct node * node,char * next_nodes[])34099a2dd95SBruce Richardson node_copy_edges(struct node *node, char *next_nodes[])
34199a2dd95SBruce Richardson {
34299a2dd95SBruce Richardson rte_edge_t i;
34399a2dd95SBruce Richardson
34499a2dd95SBruce Richardson for (i = 0; i < node->nb_edges; i++)
34599a2dd95SBruce Richardson next_nodes[i] = node->next_nodes[i];
34699a2dd95SBruce Richardson
34799a2dd95SBruce Richardson return i;
34899a2dd95SBruce Richardson }
34999a2dd95SBruce Richardson
35099a2dd95SBruce Richardson rte_node_t
rte_node_edge_get(rte_node_t id,char * next_nodes[])35199a2dd95SBruce Richardson rte_node_edge_get(rte_node_t id, char *next_nodes[])
35299a2dd95SBruce Richardson {
35399a2dd95SBruce Richardson rte_node_t rc = RTE_NODE_ID_INVALID;
35499a2dd95SBruce Richardson struct node *node;
35599a2dd95SBruce Richardson
35699a2dd95SBruce Richardson NODE_ID_CHECK(id);
35799a2dd95SBruce Richardson graph_spinlock_lock();
35899a2dd95SBruce Richardson
35999a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) {
36099a2dd95SBruce Richardson if (node->id == id) {
36199a2dd95SBruce Richardson if (next_nodes == NULL)
36299a2dd95SBruce Richardson rc = sizeof(char *) * node->nb_edges;
36399a2dd95SBruce Richardson else
36499a2dd95SBruce Richardson rc = node_copy_edges(node, next_nodes);
36599a2dd95SBruce Richardson break;
36699a2dd95SBruce Richardson }
36799a2dd95SBruce Richardson }
36899a2dd95SBruce Richardson
36999a2dd95SBruce Richardson graph_spinlock_unlock();
37099a2dd95SBruce Richardson fail:
37199a2dd95SBruce Richardson return rc;
37299a2dd95SBruce Richardson }
37399a2dd95SBruce Richardson
37499a2dd95SBruce Richardson static void
node_scan_dump(FILE * f,rte_node_t id,bool all)37599a2dd95SBruce Richardson node_scan_dump(FILE *f, rte_node_t id, bool all)
37699a2dd95SBruce Richardson {
37799a2dd95SBruce Richardson struct node *node;
37899a2dd95SBruce Richardson
37999a2dd95SBruce Richardson RTE_ASSERT(f != NULL);
38099a2dd95SBruce Richardson NODE_ID_CHECK(id);
38199a2dd95SBruce Richardson
38299a2dd95SBruce Richardson STAILQ_FOREACH(node, &node_list, next) {
38399a2dd95SBruce Richardson if (all == true) {
38499a2dd95SBruce Richardson node_dump(f, node);
38599a2dd95SBruce Richardson } else if (node->id == id) {
38699a2dd95SBruce Richardson node_dump(f, node);
38799a2dd95SBruce Richardson return;
38899a2dd95SBruce Richardson }
38999a2dd95SBruce Richardson }
39099a2dd95SBruce Richardson fail:
39199a2dd95SBruce Richardson return;
39299a2dd95SBruce Richardson }
39399a2dd95SBruce Richardson
39499a2dd95SBruce Richardson void
rte_node_dump(FILE * f,rte_node_t id)39599a2dd95SBruce Richardson rte_node_dump(FILE *f, rte_node_t id)
39699a2dd95SBruce Richardson {
39799a2dd95SBruce Richardson node_scan_dump(f, id, false);
39899a2dd95SBruce Richardson }
39999a2dd95SBruce Richardson
40099a2dd95SBruce Richardson void
rte_node_list_dump(FILE * f)40199a2dd95SBruce Richardson rte_node_list_dump(FILE *f)
40299a2dd95SBruce Richardson {
40399a2dd95SBruce Richardson node_scan_dump(f, 0, true);
40499a2dd95SBruce Richardson }
40599a2dd95SBruce Richardson
40699a2dd95SBruce Richardson rte_node_t
rte_node_max_count(void)40799a2dd95SBruce Richardson rte_node_max_count(void)
40899a2dd95SBruce Richardson {
40999a2dd95SBruce Richardson return node_id;
41099a2dd95SBruce Richardson }
411