xref: /dpdk/lib/graph/node.c (revision 99cc0a9ab6730d4df70dba4b19e78e87ad7ba110)
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 
8899a2dd95SBruce Richardson 	/* Initialize the node */
89dbba7c9eSThomas Monjalon 	if (rte_strscpy(node->name, reg->name, RTE_NODE_NAMESIZE) < 0)
9099a2dd95SBruce Richardson 		goto free;
9199a2dd95SBruce Richardson 	node->flags = reg->flags;
9299a2dd95SBruce Richardson 	node->process = reg->process;
9399a2dd95SBruce Richardson 	node->init = reg->init;
9499a2dd95SBruce Richardson 	node->fini = reg->fini;
9599a2dd95SBruce Richardson 	node->nb_edges = reg->nb_edges;
9699a2dd95SBruce Richardson 	node->parent_id = reg->parent_id;
9799a2dd95SBruce Richardson 	for (i = 0; i < reg->nb_edges; i++) {
9899a2dd95SBruce Richardson 		if (rte_strscpy(node->next_nodes[i], reg->next_nodes[i],
99dbba7c9eSThomas Monjalon 				RTE_NODE_NAMESIZE) < 0)
10099a2dd95SBruce Richardson 			goto free;
10199a2dd95SBruce Richardson 	}
10299a2dd95SBruce Richardson 
10399a2dd95SBruce Richardson 	node->id = node_id++;
10499a2dd95SBruce Richardson 
10599a2dd95SBruce Richardson 	/* Add the node at tail */
10699a2dd95SBruce Richardson 	STAILQ_INSERT_TAIL(&node_list, node, next);
10799a2dd95SBruce Richardson 	graph_spinlock_unlock();
10899a2dd95SBruce Richardson 
10999a2dd95SBruce Richardson 	return node->id;
11099a2dd95SBruce Richardson free:
11199a2dd95SBruce Richardson 	free(node);
11299a2dd95SBruce Richardson fail:
11399a2dd95SBruce Richardson 	graph_spinlock_unlock();
11499a2dd95SBruce Richardson 	return RTE_NODE_ID_INVALID;
11599a2dd95SBruce Richardson }
11699a2dd95SBruce Richardson 
11799a2dd95SBruce Richardson static int
11899a2dd95SBruce Richardson clone_name(struct rte_node_register *reg, struct node *node, const char *name)
11999a2dd95SBruce Richardson {
12099a2dd95SBruce Richardson 	ssize_t sz, rc;
12199a2dd95SBruce Richardson 
12299a2dd95SBruce Richardson #define SZ RTE_NODE_NAMESIZE
12399a2dd95SBruce Richardson 	rc = rte_strscpy(reg->name, node->name, SZ);
12499a2dd95SBruce Richardson 	if (rc < 0)
12599a2dd95SBruce Richardson 		goto fail;
12699a2dd95SBruce Richardson 	sz = rc;
12799a2dd95SBruce Richardson 	rc = rte_strscpy(reg->name + sz, "-", RTE_MAX((int16_t)(SZ - sz), 0));
12899a2dd95SBruce Richardson 	if (rc < 0)
12999a2dd95SBruce Richardson 		goto fail;
13099a2dd95SBruce Richardson 	sz += rc;
13199a2dd95SBruce Richardson 	sz = rte_strscpy(reg->name + sz, name, RTE_MAX((int16_t)(SZ - sz), 0));
13299a2dd95SBruce Richardson 	if (sz < 0)
13399a2dd95SBruce Richardson 		goto fail;
13499a2dd95SBruce Richardson 
13599a2dd95SBruce Richardson 	return 0;
13699a2dd95SBruce Richardson fail:
13799a2dd95SBruce Richardson 	rte_errno = E2BIG;
13899a2dd95SBruce Richardson 	return -rte_errno;
13999a2dd95SBruce Richardson }
14099a2dd95SBruce Richardson 
14199a2dd95SBruce Richardson static rte_node_t
14299a2dd95SBruce Richardson node_clone(struct node *node, const char *name)
14399a2dd95SBruce Richardson {
14499a2dd95SBruce Richardson 	rte_node_t rc = RTE_NODE_ID_INVALID;
14599a2dd95SBruce Richardson 	struct rte_node_register *reg;
14699a2dd95SBruce Richardson 	rte_edge_t i;
14799a2dd95SBruce Richardson 
14899a2dd95SBruce Richardson 	/* Don't allow to clone a node from a cloned node */
14999a2dd95SBruce Richardson 	if (node->parent_id != RTE_NODE_ID_INVALID) {
15099a2dd95SBruce Richardson 		rte_errno = EEXIST;
15199a2dd95SBruce Richardson 		goto fail;
15299a2dd95SBruce Richardson 	}
15399a2dd95SBruce Richardson 
15499a2dd95SBruce Richardson 	reg = calloc(1, sizeof(*reg) + (sizeof(char *) * node->nb_edges));
15599a2dd95SBruce Richardson 	if (reg == NULL) {
15699a2dd95SBruce Richardson 		rte_errno = ENOMEM;
15799a2dd95SBruce Richardson 		goto fail;
15899a2dd95SBruce Richardson 	}
15999a2dd95SBruce Richardson 
16099a2dd95SBruce Richardson 	/* Clone the source node */
16199a2dd95SBruce Richardson 	reg->flags = node->flags;
16299a2dd95SBruce Richardson 	reg->process = node->process;
16399a2dd95SBruce Richardson 	reg->init = node->init;
16499a2dd95SBruce Richardson 	reg->fini = node->fini;
16599a2dd95SBruce Richardson 	reg->nb_edges = node->nb_edges;
16699a2dd95SBruce Richardson 	reg->parent_id = node->id;
16799a2dd95SBruce Richardson 
16899a2dd95SBruce Richardson 	for (i = 0; i < node->nb_edges; i++)
16999a2dd95SBruce Richardson 		reg->next_nodes[i] = node->next_nodes[i];
17099a2dd95SBruce Richardson 
17199a2dd95SBruce Richardson 	/* Naming ceremony of the new node. name is node->name + "-" + name */
17299a2dd95SBruce Richardson 	if (clone_name(reg, node, name))
17399a2dd95SBruce Richardson 		goto free;
17499a2dd95SBruce Richardson 
17599a2dd95SBruce Richardson 	rc = __rte_node_register(reg);
17699a2dd95SBruce Richardson free:
17799a2dd95SBruce Richardson 	free(reg);
17899a2dd95SBruce Richardson fail:
17999a2dd95SBruce Richardson 	return rc;
18099a2dd95SBruce Richardson }
18199a2dd95SBruce Richardson 
18299a2dd95SBruce Richardson rte_node_t
18399a2dd95SBruce Richardson rte_node_clone(rte_node_t id, const char *name)
18499a2dd95SBruce Richardson {
18599a2dd95SBruce Richardson 	struct node *node;
18699a2dd95SBruce Richardson 
18799a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
18899a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next)
18999a2dd95SBruce Richardson 		if (node->id == id)
19099a2dd95SBruce Richardson 			return node_clone(node, name);
19199a2dd95SBruce Richardson 
19299a2dd95SBruce Richardson fail:
19399a2dd95SBruce Richardson 	return RTE_NODE_ID_INVALID;
19499a2dd95SBruce Richardson }
19599a2dd95SBruce Richardson 
19699a2dd95SBruce Richardson rte_node_t
19799a2dd95SBruce Richardson rte_node_from_name(const char *name)
19899a2dd95SBruce Richardson {
19999a2dd95SBruce Richardson 	struct node *node;
20099a2dd95SBruce Richardson 
20199a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next)
20299a2dd95SBruce Richardson 		if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0)
20399a2dd95SBruce Richardson 			return node->id;
20499a2dd95SBruce Richardson 
20599a2dd95SBruce Richardson 	return RTE_NODE_ID_INVALID;
20699a2dd95SBruce Richardson }
20799a2dd95SBruce Richardson 
20899a2dd95SBruce Richardson char *
20999a2dd95SBruce Richardson rte_node_id_to_name(rte_node_t id)
21099a2dd95SBruce Richardson {
21199a2dd95SBruce Richardson 	struct node *node;
21299a2dd95SBruce Richardson 
21399a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
21499a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next)
21599a2dd95SBruce Richardson 		if (node->id == id)
21699a2dd95SBruce Richardson 			return node->name;
21799a2dd95SBruce Richardson 
21899a2dd95SBruce Richardson fail:
21999a2dd95SBruce Richardson 	return NULL;
22099a2dd95SBruce Richardson }
22199a2dd95SBruce Richardson 
22299a2dd95SBruce Richardson rte_edge_t
22399a2dd95SBruce Richardson rte_node_edge_count(rte_node_t id)
22499a2dd95SBruce Richardson {
22599a2dd95SBruce Richardson 	struct node *node;
22699a2dd95SBruce Richardson 
22799a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
22899a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next)
22999a2dd95SBruce Richardson 		if (node->id == id)
23099a2dd95SBruce Richardson 			return node->nb_edges;
23199a2dd95SBruce Richardson fail:
23299a2dd95SBruce Richardson 	return RTE_EDGE_ID_INVALID;
23399a2dd95SBruce Richardson }
23499a2dd95SBruce Richardson 
23599a2dd95SBruce Richardson static rte_edge_t
23699a2dd95SBruce Richardson edge_update(struct node *node, struct node *prev, rte_edge_t from,
23799a2dd95SBruce Richardson 	    const char **next_nodes, rte_edge_t nb_edges)
23899a2dd95SBruce Richardson {
23999a2dd95SBruce Richardson 	rte_edge_t i, max_edges, count = 0;
24099a2dd95SBruce Richardson 	struct node *new_node;
24199a2dd95SBruce Richardson 	bool need_realloc;
24299a2dd95SBruce Richardson 	size_t sz;
24399a2dd95SBruce Richardson 
24499a2dd95SBruce Richardson 	if (from == RTE_EDGE_ID_INVALID)
24599a2dd95SBruce Richardson 		from = node->nb_edges;
24699a2dd95SBruce Richardson 
24799a2dd95SBruce Richardson 	/* Don't create hole in next_nodes[] list */
24899a2dd95SBruce Richardson 	if (from > node->nb_edges) {
24999a2dd95SBruce Richardson 		rte_errno = ENOMEM;
25099a2dd95SBruce Richardson 		goto fail;
25199a2dd95SBruce Richardson 	}
25299a2dd95SBruce Richardson 
25399a2dd95SBruce Richardson 	/* Remove me from list */
25499a2dd95SBruce Richardson 	STAILQ_REMOVE(&node_list, node, node, next);
25599a2dd95SBruce Richardson 
25699a2dd95SBruce Richardson 	/* Allocate the storage space for new node if required */
25799a2dd95SBruce Richardson 	max_edges = from + nb_edges;
25899a2dd95SBruce Richardson 	need_realloc = max_edges > node->nb_edges;
25999a2dd95SBruce Richardson 	if (need_realloc) {
26099a2dd95SBruce Richardson 		sz = sizeof(struct node) + (max_edges * RTE_NODE_NAMESIZE);
26199a2dd95SBruce Richardson 		new_node = realloc(node, sz);
26299a2dd95SBruce Richardson 		if (new_node == NULL) {
26399a2dd95SBruce Richardson 			rte_errno = ENOMEM;
26499a2dd95SBruce Richardson 			goto restore;
26599a2dd95SBruce Richardson 		} else {
26699a2dd95SBruce Richardson 			node = new_node;
26799a2dd95SBruce Richardson 		}
26899a2dd95SBruce Richardson 	}
26999a2dd95SBruce Richardson 
27099a2dd95SBruce Richardson 	/* Update the new nodes name */
27199a2dd95SBruce Richardson 	for (i = from; i < max_edges; i++, count++) {
27299a2dd95SBruce Richardson 		if (rte_strscpy(node->next_nodes[i], next_nodes[count],
273dbba7c9eSThomas Monjalon 				RTE_NODE_NAMESIZE) < 0)
27499a2dd95SBruce Richardson 			goto restore;
27599a2dd95SBruce Richardson 	}
27699a2dd95SBruce Richardson restore:
27799a2dd95SBruce Richardson 	/* Update the linked list to point new node address in prev node */
27899a2dd95SBruce Richardson 	if (prev)
27999a2dd95SBruce Richardson 		STAILQ_INSERT_AFTER(&node_list, prev, node, next);
28099a2dd95SBruce Richardson 	else
28199a2dd95SBruce Richardson 		STAILQ_INSERT_HEAD(&node_list, node, next);
28299a2dd95SBruce Richardson 
28399a2dd95SBruce Richardson 	if (need_realloc)
28499a2dd95SBruce Richardson 		node->nb_edges = max_edges;
28599a2dd95SBruce Richardson 
28699a2dd95SBruce Richardson fail:
28799a2dd95SBruce Richardson 	return count;
28899a2dd95SBruce Richardson }
28999a2dd95SBruce Richardson 
29099a2dd95SBruce Richardson rte_edge_t
29199a2dd95SBruce Richardson rte_node_edge_shrink(rte_node_t id, rte_edge_t size)
29299a2dd95SBruce Richardson {
29399a2dd95SBruce Richardson 	rte_edge_t rc = RTE_EDGE_ID_INVALID;
29499a2dd95SBruce Richardson 	struct node *node;
29599a2dd95SBruce Richardson 
29699a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
29799a2dd95SBruce Richardson 	graph_spinlock_lock();
29899a2dd95SBruce Richardson 
29999a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next) {
30099a2dd95SBruce Richardson 		if (node->id == id) {
30199a2dd95SBruce Richardson 			if (node->nb_edges < size) {
30299a2dd95SBruce Richardson 				rte_errno = E2BIG;
303*99cc0a9aSDavid Marchand 			} else {
30499a2dd95SBruce Richardson 				node->nb_edges = size;
30599a2dd95SBruce Richardson 				rc = size;
306*99cc0a9aSDavid Marchand 			}
30799a2dd95SBruce Richardson 			break;
30899a2dd95SBruce Richardson 		}
30999a2dd95SBruce Richardson 	}
31099a2dd95SBruce Richardson 
31199a2dd95SBruce Richardson 	graph_spinlock_unlock();
312*99cc0a9aSDavid Marchand fail:
31399a2dd95SBruce Richardson 	return rc;
31499a2dd95SBruce Richardson }
31599a2dd95SBruce Richardson 
31699a2dd95SBruce Richardson rte_edge_t
31799a2dd95SBruce Richardson rte_node_edge_update(rte_node_t id, rte_edge_t from, const char **next_nodes,
31899a2dd95SBruce Richardson 		     uint16_t nb_edges)
31999a2dd95SBruce Richardson {
32099a2dd95SBruce Richardson 	rte_edge_t rc = RTE_EDGE_ID_INVALID;
32199a2dd95SBruce Richardson 	struct node *n, *prev;
32299a2dd95SBruce Richardson 
32399a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
32499a2dd95SBruce Richardson 	graph_spinlock_lock();
32599a2dd95SBruce Richardson 
32699a2dd95SBruce Richardson 	prev = NULL;
32799a2dd95SBruce Richardson 	STAILQ_FOREACH(n, &node_list, next) {
32899a2dd95SBruce Richardson 		if (n->id == id) {
32999a2dd95SBruce Richardson 			rc = edge_update(n, prev, from, next_nodes, nb_edges);
33099a2dd95SBruce Richardson 			break;
33199a2dd95SBruce Richardson 		}
33299a2dd95SBruce Richardson 		prev = n;
33399a2dd95SBruce Richardson 	}
33499a2dd95SBruce Richardson 
33599a2dd95SBruce Richardson 	graph_spinlock_unlock();
33699a2dd95SBruce Richardson fail:
33799a2dd95SBruce Richardson 	return rc;
33899a2dd95SBruce Richardson }
33999a2dd95SBruce Richardson 
34099a2dd95SBruce Richardson static rte_node_t
34199a2dd95SBruce Richardson node_copy_edges(struct node *node, char *next_nodes[])
34299a2dd95SBruce Richardson {
34399a2dd95SBruce Richardson 	rte_edge_t i;
34499a2dd95SBruce Richardson 
34599a2dd95SBruce Richardson 	for (i = 0; i < node->nb_edges; i++)
34699a2dd95SBruce Richardson 		next_nodes[i] = node->next_nodes[i];
34799a2dd95SBruce Richardson 
34899a2dd95SBruce Richardson 	return i;
34999a2dd95SBruce Richardson }
35099a2dd95SBruce Richardson 
35199a2dd95SBruce Richardson rte_node_t
35299a2dd95SBruce Richardson rte_node_edge_get(rte_node_t id, char *next_nodes[])
35399a2dd95SBruce Richardson {
35499a2dd95SBruce Richardson 	rte_node_t rc = RTE_NODE_ID_INVALID;
35599a2dd95SBruce Richardson 	struct node *node;
35699a2dd95SBruce Richardson 
35799a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
35899a2dd95SBruce Richardson 	graph_spinlock_lock();
35999a2dd95SBruce Richardson 
36099a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next) {
36199a2dd95SBruce Richardson 		if (node->id == id) {
36299a2dd95SBruce Richardson 			if (next_nodes == NULL)
36399a2dd95SBruce Richardson 				rc = sizeof(char *) * node->nb_edges;
36499a2dd95SBruce Richardson 			else
36599a2dd95SBruce Richardson 				rc = node_copy_edges(node, next_nodes);
36699a2dd95SBruce Richardson 			break;
36799a2dd95SBruce Richardson 		}
36899a2dd95SBruce Richardson 	}
36999a2dd95SBruce Richardson 
37099a2dd95SBruce Richardson 	graph_spinlock_unlock();
37199a2dd95SBruce Richardson fail:
37299a2dd95SBruce Richardson 	return rc;
37399a2dd95SBruce Richardson }
37499a2dd95SBruce Richardson 
37599a2dd95SBruce Richardson static void
37699a2dd95SBruce Richardson node_scan_dump(FILE *f, rte_node_t id, bool all)
37799a2dd95SBruce Richardson {
37899a2dd95SBruce Richardson 	struct node *node;
37999a2dd95SBruce Richardson 
38099a2dd95SBruce Richardson 	RTE_ASSERT(f != NULL);
38199a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
38299a2dd95SBruce Richardson 
38399a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next) {
38499a2dd95SBruce Richardson 		if (all == true) {
38599a2dd95SBruce Richardson 			node_dump(f, node);
38699a2dd95SBruce Richardson 		} else if (node->id == id) {
38799a2dd95SBruce Richardson 			node_dump(f, node);
38899a2dd95SBruce Richardson 			return;
38999a2dd95SBruce Richardson 		}
39099a2dd95SBruce Richardson 	}
39199a2dd95SBruce Richardson fail:
39299a2dd95SBruce Richardson 	return;
39399a2dd95SBruce Richardson }
39499a2dd95SBruce Richardson 
39599a2dd95SBruce Richardson void
39699a2dd95SBruce Richardson rte_node_dump(FILE *f, rte_node_t id)
39799a2dd95SBruce Richardson {
39899a2dd95SBruce Richardson 	node_scan_dump(f, id, false);
39999a2dd95SBruce Richardson }
40099a2dd95SBruce Richardson 
40199a2dd95SBruce Richardson void
40299a2dd95SBruce Richardson rte_node_list_dump(FILE *f)
40399a2dd95SBruce Richardson {
40499a2dd95SBruce Richardson 	node_scan_dump(f, 0, true);
40599a2dd95SBruce Richardson }
40699a2dd95SBruce Richardson 
40799a2dd95SBruce Richardson rte_node_t
40899a2dd95SBruce Richardson rte_node_max_count(void)
40999a2dd95SBruce Richardson {
41099a2dd95SBruce Richardson 	return node_id;
41199a2dd95SBruce Richardson }
412