xref: /dpdk/lib/graph/node.c (revision dbba7c9efbb9ed5cfc88c192213f54b1f9942c00)
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_eal.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 */
89*dbba7c9eSThomas 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],
99*dbba7c9eSThomas 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 	/* Check for duplicate name */
15599a2dd95SBruce Richardson 	if (node_has_duplicate_entry(name))
15699a2dd95SBruce Richardson 		goto fail;
15799a2dd95SBruce Richardson 
15899a2dd95SBruce Richardson 	reg = calloc(1, sizeof(*reg) + (sizeof(char *) * node->nb_edges));
15999a2dd95SBruce Richardson 	if (reg == NULL) {
16099a2dd95SBruce Richardson 		rte_errno = ENOMEM;
16199a2dd95SBruce Richardson 		goto fail;
16299a2dd95SBruce Richardson 	}
16399a2dd95SBruce Richardson 
16499a2dd95SBruce Richardson 	/* Clone the source node */
16599a2dd95SBruce Richardson 	reg->flags = node->flags;
16699a2dd95SBruce Richardson 	reg->process = node->process;
16799a2dd95SBruce Richardson 	reg->init = node->init;
16899a2dd95SBruce Richardson 	reg->fini = node->fini;
16999a2dd95SBruce Richardson 	reg->nb_edges = node->nb_edges;
17099a2dd95SBruce Richardson 	reg->parent_id = node->id;
17199a2dd95SBruce Richardson 
17299a2dd95SBruce Richardson 	for (i = 0; i < node->nb_edges; i++)
17399a2dd95SBruce Richardson 		reg->next_nodes[i] = node->next_nodes[i];
17499a2dd95SBruce Richardson 
17599a2dd95SBruce Richardson 	/* Naming ceremony of the new node. name is node->name + "-" + name */
17699a2dd95SBruce Richardson 	if (clone_name(reg, node, name))
17799a2dd95SBruce Richardson 		goto free;
17899a2dd95SBruce Richardson 
17999a2dd95SBruce Richardson 	rc = __rte_node_register(reg);
18099a2dd95SBruce Richardson free:
18199a2dd95SBruce Richardson 	free(reg);
18299a2dd95SBruce Richardson fail:
18399a2dd95SBruce Richardson 	return rc;
18499a2dd95SBruce Richardson }
18599a2dd95SBruce Richardson 
18699a2dd95SBruce Richardson rte_node_t
18799a2dd95SBruce Richardson rte_node_clone(rte_node_t id, const char *name)
18899a2dd95SBruce Richardson {
18999a2dd95SBruce Richardson 	struct node *node;
19099a2dd95SBruce Richardson 
19199a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
19299a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next)
19399a2dd95SBruce Richardson 		if (node->id == id)
19499a2dd95SBruce Richardson 			return node_clone(node, name);
19599a2dd95SBruce Richardson 
19699a2dd95SBruce Richardson fail:
19799a2dd95SBruce Richardson 	return RTE_NODE_ID_INVALID;
19899a2dd95SBruce Richardson }
19999a2dd95SBruce Richardson 
20099a2dd95SBruce Richardson rte_node_t
20199a2dd95SBruce Richardson rte_node_from_name(const char *name)
20299a2dd95SBruce Richardson {
20399a2dd95SBruce Richardson 	struct node *node;
20499a2dd95SBruce Richardson 
20599a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next)
20699a2dd95SBruce Richardson 		if (strncmp(node->name, name, RTE_NODE_NAMESIZE) == 0)
20799a2dd95SBruce Richardson 			return node->id;
20899a2dd95SBruce Richardson 
20999a2dd95SBruce Richardson 	return RTE_NODE_ID_INVALID;
21099a2dd95SBruce Richardson }
21199a2dd95SBruce Richardson 
21299a2dd95SBruce Richardson char *
21399a2dd95SBruce Richardson rte_node_id_to_name(rte_node_t id)
21499a2dd95SBruce Richardson {
21599a2dd95SBruce Richardson 	struct node *node;
21699a2dd95SBruce Richardson 
21799a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
21899a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next)
21999a2dd95SBruce Richardson 		if (node->id == id)
22099a2dd95SBruce Richardson 			return node->name;
22199a2dd95SBruce Richardson 
22299a2dd95SBruce Richardson fail:
22399a2dd95SBruce Richardson 	return NULL;
22499a2dd95SBruce Richardson }
22599a2dd95SBruce Richardson 
22699a2dd95SBruce Richardson rte_edge_t
22799a2dd95SBruce Richardson rte_node_edge_count(rte_node_t id)
22899a2dd95SBruce Richardson {
22999a2dd95SBruce Richardson 	struct node *node;
23099a2dd95SBruce Richardson 
23199a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
23299a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next)
23399a2dd95SBruce Richardson 		if (node->id == id)
23499a2dd95SBruce Richardson 			return node->nb_edges;
23599a2dd95SBruce Richardson fail:
23699a2dd95SBruce Richardson 	return RTE_EDGE_ID_INVALID;
23799a2dd95SBruce Richardson }
23899a2dd95SBruce Richardson 
23999a2dd95SBruce Richardson static rte_edge_t
24099a2dd95SBruce Richardson edge_update(struct node *node, struct node *prev, rte_edge_t from,
24199a2dd95SBruce Richardson 	    const char **next_nodes, rte_edge_t nb_edges)
24299a2dd95SBruce Richardson {
24399a2dd95SBruce Richardson 	rte_edge_t i, max_edges, count = 0;
24499a2dd95SBruce Richardson 	struct node *new_node;
24599a2dd95SBruce Richardson 	bool need_realloc;
24699a2dd95SBruce Richardson 	size_t sz;
24799a2dd95SBruce Richardson 
24899a2dd95SBruce Richardson 	if (from == RTE_EDGE_ID_INVALID)
24999a2dd95SBruce Richardson 		from = node->nb_edges;
25099a2dd95SBruce Richardson 
25199a2dd95SBruce Richardson 	/* Don't create hole in next_nodes[] list */
25299a2dd95SBruce Richardson 	if (from > node->nb_edges) {
25399a2dd95SBruce Richardson 		rte_errno = ENOMEM;
25499a2dd95SBruce Richardson 		goto fail;
25599a2dd95SBruce Richardson 	}
25699a2dd95SBruce Richardson 
25799a2dd95SBruce Richardson 	/* Remove me from list */
25899a2dd95SBruce Richardson 	STAILQ_REMOVE(&node_list, node, node, next);
25999a2dd95SBruce Richardson 
26099a2dd95SBruce Richardson 	/* Allocate the storage space for new node if required */
26199a2dd95SBruce Richardson 	max_edges = from + nb_edges;
26299a2dd95SBruce Richardson 	need_realloc = max_edges > node->nb_edges;
26399a2dd95SBruce Richardson 	if (need_realloc) {
26499a2dd95SBruce Richardson 		sz = sizeof(struct node) + (max_edges * RTE_NODE_NAMESIZE);
26599a2dd95SBruce Richardson 		new_node = realloc(node, sz);
26699a2dd95SBruce Richardson 		if (new_node == NULL) {
26799a2dd95SBruce Richardson 			rte_errno = ENOMEM;
26899a2dd95SBruce Richardson 			goto restore;
26999a2dd95SBruce Richardson 		} else {
27099a2dd95SBruce Richardson 			node = new_node;
27199a2dd95SBruce Richardson 		}
27299a2dd95SBruce Richardson 	}
27399a2dd95SBruce Richardson 
27499a2dd95SBruce Richardson 	/* Update the new nodes name */
27599a2dd95SBruce Richardson 	for (i = from; i < max_edges; i++, count++) {
27699a2dd95SBruce Richardson 		if (rte_strscpy(node->next_nodes[i], next_nodes[count],
277*dbba7c9eSThomas Monjalon 				RTE_NODE_NAMESIZE) < 0)
27899a2dd95SBruce Richardson 			goto restore;
27999a2dd95SBruce Richardson 	}
28099a2dd95SBruce Richardson restore:
28199a2dd95SBruce Richardson 	/* Update the linked list to point new node address in prev node */
28299a2dd95SBruce Richardson 	if (prev)
28399a2dd95SBruce Richardson 		STAILQ_INSERT_AFTER(&node_list, prev, node, next);
28499a2dd95SBruce Richardson 	else
28599a2dd95SBruce Richardson 		STAILQ_INSERT_HEAD(&node_list, node, next);
28699a2dd95SBruce Richardson 
28799a2dd95SBruce Richardson 	if (need_realloc)
28899a2dd95SBruce Richardson 		node->nb_edges = max_edges;
28999a2dd95SBruce Richardson 
29099a2dd95SBruce Richardson fail:
29199a2dd95SBruce Richardson 	return count;
29299a2dd95SBruce Richardson }
29399a2dd95SBruce Richardson 
29499a2dd95SBruce Richardson rte_edge_t
29599a2dd95SBruce Richardson rte_node_edge_shrink(rte_node_t id, rte_edge_t size)
29699a2dd95SBruce Richardson {
29799a2dd95SBruce Richardson 	rte_edge_t rc = RTE_EDGE_ID_INVALID;
29899a2dd95SBruce Richardson 	struct node *node;
29999a2dd95SBruce Richardson 
30099a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
30199a2dd95SBruce Richardson 	graph_spinlock_lock();
30299a2dd95SBruce Richardson 
30399a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next) {
30499a2dd95SBruce Richardson 		if (node->id == id) {
30599a2dd95SBruce Richardson 			if (node->nb_edges < size) {
30699a2dd95SBruce Richardson 				rte_errno = E2BIG;
30799a2dd95SBruce Richardson 				goto fail;
30899a2dd95SBruce Richardson 			}
30999a2dd95SBruce Richardson 			node->nb_edges = size;
31099a2dd95SBruce Richardson 			rc = size;
31199a2dd95SBruce Richardson 			break;
31299a2dd95SBruce Richardson 		}
31399a2dd95SBruce Richardson 	}
31499a2dd95SBruce Richardson 
31599a2dd95SBruce Richardson fail:
31699a2dd95SBruce Richardson 	graph_spinlock_unlock();
31799a2dd95SBruce Richardson 	return rc;
31899a2dd95SBruce Richardson }
31999a2dd95SBruce Richardson 
32099a2dd95SBruce Richardson rte_edge_t
32199a2dd95SBruce Richardson rte_node_edge_update(rte_node_t id, rte_edge_t from, const char **next_nodes,
32299a2dd95SBruce Richardson 		     uint16_t nb_edges)
32399a2dd95SBruce Richardson {
32499a2dd95SBruce Richardson 	rte_edge_t rc = RTE_EDGE_ID_INVALID;
32599a2dd95SBruce Richardson 	struct node *n, *prev;
32699a2dd95SBruce Richardson 
32799a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
32899a2dd95SBruce Richardson 	graph_spinlock_lock();
32999a2dd95SBruce Richardson 
33099a2dd95SBruce Richardson 	prev = NULL;
33199a2dd95SBruce Richardson 	STAILQ_FOREACH(n, &node_list, next) {
33299a2dd95SBruce Richardson 		if (n->id == id) {
33399a2dd95SBruce Richardson 			rc = edge_update(n, prev, from, next_nodes, nb_edges);
33499a2dd95SBruce Richardson 			break;
33599a2dd95SBruce Richardson 		}
33699a2dd95SBruce Richardson 		prev = n;
33799a2dd95SBruce Richardson 	}
33899a2dd95SBruce Richardson 
33999a2dd95SBruce Richardson 	graph_spinlock_unlock();
34099a2dd95SBruce Richardson fail:
34199a2dd95SBruce Richardson 	return rc;
34299a2dd95SBruce Richardson }
34399a2dd95SBruce Richardson 
34499a2dd95SBruce Richardson static rte_node_t
34599a2dd95SBruce Richardson node_copy_edges(struct node *node, char *next_nodes[])
34699a2dd95SBruce Richardson {
34799a2dd95SBruce Richardson 	rte_edge_t i;
34899a2dd95SBruce Richardson 
34999a2dd95SBruce Richardson 	for (i = 0; i < node->nb_edges; i++)
35099a2dd95SBruce Richardson 		next_nodes[i] = node->next_nodes[i];
35199a2dd95SBruce Richardson 
35299a2dd95SBruce Richardson 	return i;
35399a2dd95SBruce Richardson }
35499a2dd95SBruce Richardson 
35599a2dd95SBruce Richardson rte_node_t
35699a2dd95SBruce Richardson rte_node_edge_get(rte_node_t id, char *next_nodes[])
35799a2dd95SBruce Richardson {
35899a2dd95SBruce Richardson 	rte_node_t rc = RTE_NODE_ID_INVALID;
35999a2dd95SBruce Richardson 	struct node *node;
36099a2dd95SBruce Richardson 
36199a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
36299a2dd95SBruce Richardson 	graph_spinlock_lock();
36399a2dd95SBruce Richardson 
36499a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next) {
36599a2dd95SBruce Richardson 		if (node->id == id) {
36699a2dd95SBruce Richardson 			if (next_nodes == NULL)
36799a2dd95SBruce Richardson 				rc = sizeof(char *) * node->nb_edges;
36899a2dd95SBruce Richardson 			else
36999a2dd95SBruce Richardson 				rc = node_copy_edges(node, next_nodes);
37099a2dd95SBruce Richardson 			break;
37199a2dd95SBruce Richardson 		}
37299a2dd95SBruce Richardson 	}
37399a2dd95SBruce Richardson 
37499a2dd95SBruce Richardson 	graph_spinlock_unlock();
37599a2dd95SBruce Richardson fail:
37699a2dd95SBruce Richardson 	return rc;
37799a2dd95SBruce Richardson }
37899a2dd95SBruce Richardson 
37999a2dd95SBruce Richardson static void
38099a2dd95SBruce Richardson node_scan_dump(FILE *f, rte_node_t id, bool all)
38199a2dd95SBruce Richardson {
38299a2dd95SBruce Richardson 	struct node *node;
38399a2dd95SBruce Richardson 
38499a2dd95SBruce Richardson 	RTE_ASSERT(f != NULL);
38599a2dd95SBruce Richardson 	NODE_ID_CHECK(id);
38699a2dd95SBruce Richardson 
38799a2dd95SBruce Richardson 	STAILQ_FOREACH(node, &node_list, next) {
38899a2dd95SBruce Richardson 		if (all == true) {
38999a2dd95SBruce Richardson 			node_dump(f, node);
39099a2dd95SBruce Richardson 		} else if (node->id == id) {
39199a2dd95SBruce Richardson 			node_dump(f, node);
39299a2dd95SBruce Richardson 			return;
39399a2dd95SBruce Richardson 		}
39499a2dd95SBruce Richardson 	}
39599a2dd95SBruce Richardson fail:
39699a2dd95SBruce Richardson 	return;
39799a2dd95SBruce Richardson }
39899a2dd95SBruce Richardson 
39999a2dd95SBruce Richardson void
40099a2dd95SBruce Richardson rte_node_dump(FILE *f, rte_node_t id)
40199a2dd95SBruce Richardson {
40299a2dd95SBruce Richardson 	node_scan_dump(f, id, false);
40399a2dd95SBruce Richardson }
40499a2dd95SBruce Richardson 
40599a2dd95SBruce Richardson void
40699a2dd95SBruce Richardson rte_node_list_dump(FILE *f)
40799a2dd95SBruce Richardson {
40899a2dd95SBruce Richardson 	node_scan_dump(f, 0, true);
40999a2dd95SBruce Richardson }
41099a2dd95SBruce Richardson 
41199a2dd95SBruce Richardson rte_node_t
41299a2dd95SBruce Richardson rte_node_max_count(void)
41399a2dd95SBruce Richardson {
41499a2dd95SBruce Richardson 	return node_id;
41599a2dd95SBruce Richardson }
416