99a2dd955f
There is no reason for the DPDK libraries to all have 'librte_' prefix on the directory names. This prefix makes the directory names longer and also makes it awkward to add features referring to individual libraries in the build - should the lib names be specified with or without the prefix. Therefore, we can just remove the library prefix and use the library's unique name as the directory name, i.e. 'eal' rather than 'librte_eal' Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
170 lines
3.4 KiB
C
170 lines
3.4 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright(C) 2020 Marvell International Ltd.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
|
|
#include <rte_common.h>
|
|
#include <rte_errno.h>
|
|
|
|
#include "graph_private.h"
|
|
|
|
/* Check whether a node has next_node to itself */
|
|
static inline int
|
|
node_has_loop_edge(struct node *node)
|
|
{
|
|
rte_edge_t i;
|
|
char *name;
|
|
int rc = 0;
|
|
|
|
for (i = 0; i < node->nb_edges; i++) {
|
|
if (strncmp(node->name, node->next_nodes[i],
|
|
RTE_NODE_NAMESIZE) == 0) {
|
|
name = node->name;
|
|
rc = 1;
|
|
SET_ERR_JMP(EINVAL, fail, "Node %s has loop to self",
|
|
name);
|
|
}
|
|
}
|
|
fail:
|
|
return rc;
|
|
}
|
|
|
|
int
|
|
graph_node_has_loop_edge(struct graph *graph)
|
|
{
|
|
struct graph_node *graph_node;
|
|
|
|
STAILQ_FOREACH(graph_node, &graph->node_list, next)
|
|
if (node_has_loop_edge(graph_node->node))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
rte_node_t
|
|
graph_src_nodes_count(struct graph *graph)
|
|
{
|
|
struct graph_node *graph_node;
|
|
rte_node_t rc = 0;
|
|
|
|
STAILQ_FOREACH(graph_node, &graph->node_list, next)
|
|
if (graph_node->node->flags & RTE_NODE_SOURCE_F)
|
|
rc++;
|
|
|
|
if (rc == 0)
|
|
SET_ERR_JMP(EINVAL, fail, "Graph needs at least a source node");
|
|
fail:
|
|
return rc;
|
|
}
|
|
|
|
/* Check whether a node has next_node to a source node */
|
|
int
|
|
graph_node_has_edge_to_src_node(struct graph *graph)
|
|
{
|
|
struct graph_node *graph_node;
|
|
struct node *node;
|
|
rte_edge_t i;
|
|
|
|
STAILQ_FOREACH(graph_node, &graph->node_list, next) {
|
|
for (i = 0; i < graph_node->node->nb_edges; i++) {
|
|
node = graph_node->adjacency_list[i]->node;
|
|
if (node->flags & RTE_NODE_SOURCE_F)
|
|
SET_ERR_JMP(
|
|
EEXIST, fail,
|
|
"Node %s points to the source node %s",
|
|
graph_node->node->name, node->name);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
fail:
|
|
return 1;
|
|
}
|
|
|
|
rte_node_t
|
|
graph_nodes_count(struct graph *graph)
|
|
{
|
|
struct graph_node *graph_node;
|
|
rte_node_t count = 0;
|
|
|
|
STAILQ_FOREACH(graph_node, &graph->node_list, next)
|
|
count++;
|
|
|
|
return count;
|
|
}
|
|
|
|
void
|
|
graph_mark_nodes_as_not_visited(struct graph *graph)
|
|
{
|
|
struct graph_node *graph_node;
|
|
|
|
STAILQ_FOREACH(graph_node, &graph->node_list, next)
|
|
graph_node->visited = false;
|
|
}
|
|
|
|
int
|
|
graph_bfs(struct graph *graph, struct graph_node *start)
|
|
{
|
|
struct graph_node **queue, *v, *tmp;
|
|
uint16_t head = 0, tail = 0;
|
|
rte_edge_t i;
|
|
size_t sz;
|
|
|
|
sz = sizeof(struct graph_node *) * graph_nodes_count(graph);
|
|
queue = malloc(sz);
|
|
if (queue == NULL)
|
|
SET_ERR_JMP(ENOMEM, fail, "Failed to alloc BFS queue of %zu",
|
|
sz);
|
|
|
|
/* BFS algorithm */
|
|
queue[tail++] = start;
|
|
start->visited = true;
|
|
while (head != tail) {
|
|
v = queue[head++];
|
|
for (i = 0; i < v->node->nb_edges; i++) {
|
|
tmp = v->adjacency_list[i];
|
|
if (tmp->visited == false) {
|
|
queue[tail++] = tmp;
|
|
tmp->visited = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
free(queue);
|
|
return 0;
|
|
|
|
fail:
|
|
return -rte_errno;
|
|
}
|
|
|
|
/* Check whether a node has connected path or parent node */
|
|
int
|
|
graph_has_isolated_node(struct graph *graph)
|
|
{
|
|
struct graph_node *graph_node;
|
|
|
|
graph_mark_nodes_as_not_visited(graph);
|
|
|
|
STAILQ_FOREACH(graph_node, &graph->node_list, next) {
|
|
if (graph_node->node->flags & RTE_NODE_SOURCE_F) {
|
|
if (graph_node->node->nb_edges == 0)
|
|
SET_ERR_JMP(EINVAL, fail,
|
|
"%s node needs minimum one edge",
|
|
graph_node->node->name);
|
|
if (graph_bfs(graph, graph_node))
|
|
goto fail;
|
|
}
|
|
}
|
|
|
|
STAILQ_FOREACH(graph_node, &graph->node_list, next)
|
|
if (graph_node->visited == false)
|
|
SET_ERR_JMP(EINVAL, fail, "Found isolated node %s",
|
|
graph_node->node->name);
|
|
|
|
return 0;
|
|
fail:
|
|
return 1;
|
|
}
|