mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-16 10:38:05 +00:00
lib: Generalize graph to work for any data type
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
parent
55589d304c
commit
16d7c05093
@ -11,7 +11,7 @@ libzebra_la_LDFLAGS = -version-info 0:0:0
|
|||||||
libzebra_la_SOURCES = \
|
libzebra_la_SOURCES = \
|
||||||
network.c pid_output.c getopt.c getopt1.c daemon.c \
|
network.c pid_output.c getopt.c getopt1.c daemon.c \
|
||||||
checksum.c vector.c linklist.c vty.c \
|
checksum.c vector.c linklist.c vty.c \
|
||||||
command_graph.c command_parse.y command_lex.l command_match.c grammar_sandbox.c \
|
graph.c command_parse.y command_lex.l command_match.c grammar_sandbox.c \
|
||||||
command.c \
|
command.c \
|
||||||
sockunion.c prefix.c thread.c if.c memory.c buffer.c table.c hash.c \
|
sockunion.c prefix.c thread.c if.c memory.c buffer.c table.c hash.c \
|
||||||
filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
|
filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
|
||||||
@ -28,7 +28,7 @@ libzebra_la_LIBADD = @LIB_REGEX@ @LIBCAP@
|
|||||||
pkginclude_HEADERS = \
|
pkginclude_HEADERS = \
|
||||||
buffer.h checksum.h filter.h getopt.h hash.h \
|
buffer.h checksum.h filter.h getopt.h hash.h \
|
||||||
if.h linklist.h log.h \
|
if.h linklist.h log.h \
|
||||||
command_graph.h command_match.h grammar_sandbox.h \
|
graph.h command_match.h grammar_sandbox.h \
|
||||||
command.h \
|
command.h \
|
||||||
memory.h network.h prefix.h routemap.h distribute.h sockunion.h \
|
memory.h network.h prefix.h routemap.h distribute.h sockunion.h \
|
||||||
str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \
|
str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* Graph data structure and companion routines for CLI backend.
|
|
||||||
*
|
|
||||||
* --
|
|
||||||
* Copyright (C) 2016 Cumulus Networks, Inc.
|
|
||||||
*
|
|
||||||
* This file is part of GNU Zebra.
|
|
||||||
*
|
|
||||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2, or (at your option) any
|
|
||||||
* later version.
|
|
||||||
*
|
|
||||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with GNU Zebra; see the file COPYING. If not, write to the Free
|
|
||||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
#include <zebra.h>
|
|
||||||
#include "command_graph.h"
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
struct graph_node *
|
|
||||||
graphnode_add_child (struct graph_node *parent, struct graph_node *child)
|
|
||||||
{
|
|
||||||
vector_set (parent->children, child);
|
|
||||||
child->refs++;
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct graph_node *
|
|
||||||
graphnode_new (enum graph_node_type type)
|
|
||||||
{
|
|
||||||
struct graph_node *node =
|
|
||||||
XCALLOC(MTYPE_CMD_TOKENS, sizeof(struct graph_node));
|
|
||||||
|
|
||||||
node->type = type;
|
|
||||||
node->children = vector_init(VECTOR_MIN_SIZE);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
graphnode_delete (struct graph_node *node)
|
|
||||||
{
|
|
||||||
if (!node) return;
|
|
||||||
if (node->children) vector_free (node->children);
|
|
||||||
if (node->element) free_cmd_element (node->element);
|
|
||||||
free (node->text);
|
|
||||||
free (node->arg);
|
|
||||||
free (node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
graphnode_delete_graph (struct graph_node *start)
|
|
||||||
{
|
|
||||||
if (start && start->children && vector_active (start->children) > 0)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < vector_active (start->children); i++)
|
|
||||||
{
|
|
||||||
graphnode_delete (vector_slot(start->children, i));
|
|
||||||
vector_unset (start->children, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (--(start->refs) == 0)
|
|
||||||
graphnode_delete (start);
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* Graph data structure and companion routines for CLI backend.
|
|
||||||
*
|
|
||||||
* --
|
|
||||||
* Copyright (C) 2016 Cumulus Networks, Inc.
|
|
||||||
*
|
|
||||||
* This file is part of GNU Zebra.
|
|
||||||
*
|
|
||||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2, or (at your option) any
|
|
||||||
* later version.
|
|
||||||
*
|
|
||||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with GNU Zebra; see the file COPYING. If not, write to the Free
|
|
||||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _ZEBRA_COMMAND_GRAPH_H
|
|
||||||
#define _ZEBRA_COMMAND_GRAPH_H
|
|
||||||
|
|
||||||
#include "command.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Types for graph nodes.
|
|
||||||
*
|
|
||||||
* The node type determines what kind of data the node can match (in the
|
|
||||||
* matching use case) or hold (in the argv use case).
|
|
||||||
*/
|
|
||||||
enum graph_node_type
|
|
||||||
{
|
|
||||||
IPV4_GN, // IPV4 addresses
|
|
||||||
IPV4_PREFIX_GN, // IPV4 network prefixes
|
|
||||||
IPV6_GN, // IPV6 prefixes
|
|
||||||
IPV6_PREFIX_GN, // IPV6 network prefixes
|
|
||||||
WORD_GN, // words
|
|
||||||
RANGE_GN, // integer ranges
|
|
||||||
NUMBER_GN, // numbers
|
|
||||||
VARIABLE_GN, // almost anything
|
|
||||||
/* plumbing types */
|
|
||||||
SELECTOR_GN, // marks beginning of selector subgraph
|
|
||||||
OPTION_GN, // marks beginning of option subgraph
|
|
||||||
NUL_GN, // transparent node with various uses
|
|
||||||
START_GN, // first node in the graph (has no parents)
|
|
||||||
END_GN // leaf node in the graph, has pointer to cmd_element
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Command graph node.
|
|
||||||
* Used for matching and passing arguments to vtysh commands.
|
|
||||||
*/
|
|
||||||
struct graph_node
|
|
||||||
{
|
|
||||||
enum graph_node_type type; // data type this node matches or holds
|
|
||||||
vector children; // this node's children
|
|
||||||
|
|
||||||
char *text; // original format text
|
|
||||||
char *doc; // docstring for this node
|
|
||||||
long long value; // for NUMBER_GN
|
|
||||||
long long min, max; // for RANGE_GN
|
|
||||||
|
|
||||||
/* cmd_element struct pointer, only valid for END_GN */
|
|
||||||
struct cmd_element *element;
|
|
||||||
|
|
||||||
/* used for passing arguments to command functions */
|
|
||||||
char *arg;
|
|
||||||
|
|
||||||
/* refcount for node parents */
|
|
||||||
unsigned int refs;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a node as a child of another node.
|
|
||||||
*
|
|
||||||
* @param[in] parent node
|
|
||||||
* @param[in] child node
|
|
||||||
* @return child node
|
|
||||||
*/
|
|
||||||
struct graph_node *
|
|
||||||
graphnode_add_child (struct graph_node *parent, struct graph_node *child);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new node, initializes all fields to default values and sets the
|
|
||||||
* node type.
|
|
||||||
*
|
|
||||||
* @param[in] type node type
|
|
||||||
* @return pointer to the created node
|
|
||||||
*/
|
|
||||||
struct graph_node *
|
|
||||||
graphnode_new (enum graph_node_type type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes a graph node without deleting its children.
|
|
||||||
*
|
|
||||||
* @param[out] node pointer to node to delete
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
graphnode_delete (struct graph_node *node);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes a graph node and recursively deletes all its direct and indirect
|
|
||||||
* children.
|
|
||||||
*
|
|
||||||
* @param[out] node start node of graph to free
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
graphnode_delete_graph (struct graph_node *node);
|
|
||||||
|
|
||||||
#endif /* _ZEBRA_COMMAND_GRAPH_H */
|
|
113
lib/graph.c
Normal file
113
lib/graph.c
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Graph data structure.
|
||||||
|
*
|
||||||
|
* --
|
||||||
|
* Copyright (C) 2016 Cumulus Networks, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Zebra.
|
||||||
|
*
|
||||||
|
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Zebra; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
#include <zebra.h>
|
||||||
|
#include "command_graph.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct graph_node *
|
||||||
|
graph_new_node (struct graph *graph, void *data, void (*del) (void*))
|
||||||
|
{
|
||||||
|
struct graph_node *node =
|
||||||
|
XCALLOC(MTYPE_CMD_TOKENS, sizeof(struct graph_node));
|
||||||
|
|
||||||
|
node->from = vector_init(VECTOR_MIN_SIZE);
|
||||||
|
node->to = vector_init(VECTOR_MIN_SIZE);
|
||||||
|
node->data = data;
|
||||||
|
node->del = del;
|
||||||
|
|
||||||
|
vector_set (graph->nodes, node);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
graph_delete_node (struct graph *graph, struct graph_node *node)
|
||||||
|
{
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
// an adjacent node
|
||||||
|
struct graph_node *adj;
|
||||||
|
|
||||||
|
// for all nodes that have an edge to us, remove us from their ->to
|
||||||
|
for (int i = 0; i < vector_active (node->from); i++)
|
||||||
|
{
|
||||||
|
adj = vector_slot (node->from, i);
|
||||||
|
for (int j = 0; j < vector_active (adj->to); j++)
|
||||||
|
if (vector_slot (adj->to, j) == node)
|
||||||
|
vector_unset (adj->to, j);
|
||||||
|
|
||||||
|
// if the node is orphaned, delete it
|
||||||
|
if (vector_active (adj->to) == 0 && vector_active (adj->from) == 0)
|
||||||
|
graph_delete_node (adj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for all nodes that we have an edge to, remove us from their ->from
|
||||||
|
for (int i = 0; i < vector_active (node->to); i++)
|
||||||
|
{
|
||||||
|
adj = vector_slot (node->to, i);
|
||||||
|
for (int j = 0; j < vector_active (adj->from); j++)
|
||||||
|
if (vector_slot (adj->from, j) == node)
|
||||||
|
vector_unset (adj->from, j);
|
||||||
|
|
||||||
|
// if the node is orphaned, delete it
|
||||||
|
if (vector_active (adj->to) == 0 && vector_active (adj->from) == 0)
|
||||||
|
graph_delete_node (adj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is a deletion callback, call it!
|
||||||
|
if (node->del && node->data)
|
||||||
|
(*node->del) (node->data);
|
||||||
|
|
||||||
|
// free adjacency lists
|
||||||
|
vector_free (node->to);
|
||||||
|
vector_free (node->from);
|
||||||
|
|
||||||
|
// remove node from graph->nodes
|
||||||
|
for (int i = 0; i < vector_active (graph->nodes); i++)
|
||||||
|
if (vector_slot (graph->nodes, i) == node)
|
||||||
|
vector_unset (graph->nodes, i);
|
||||||
|
|
||||||
|
// free the node itself
|
||||||
|
free (node);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct graph_node *
|
||||||
|
graph_add_edge (struct graph_node *from, struct graph_node *to)
|
||||||
|
{
|
||||||
|
vector_set (from->to, to);
|
||||||
|
vector_set (to->from, from);
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
graph_delete_graph (struct graph *graph)
|
||||||
|
{
|
||||||
|
// delete each node in the graph
|
||||||
|
for (int i = 0; i < vector_active (graph->nodes); i++)
|
||||||
|
graph_delete_node (vector_slot (graph->nodes, i));
|
||||||
|
|
||||||
|
vector_free (graph->nodes);
|
||||||
|
free (graph);
|
||||||
|
}
|
99
lib/graph.h
Normal file
99
lib/graph.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Graph data structure.
|
||||||
|
*
|
||||||
|
* --
|
||||||
|
* Copyright (C) 2016 Cumulus Networks, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU Zebra.
|
||||||
|
*
|
||||||
|
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GNU Zebra; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ZEBRA_COMMAND_GRAPH_H
|
||||||
|
#define _ZEBRA_COMMAND_GRAPH_H
|
||||||
|
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Graph structure.
|
||||||
|
*/
|
||||||
|
struct graph
|
||||||
|
{
|
||||||
|
vector nodes; // all nodes in the graph
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Graph node / vertex.
|
||||||
|
*/
|
||||||
|
struct graph_node
|
||||||
|
{
|
||||||
|
vector from; // nodes which have edges to this node
|
||||||
|
vector to; // nodes which this node has edges to
|
||||||
|
|
||||||
|
void *data; // node data
|
||||||
|
void (*del) (void *data) // deletion callback
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new node.
|
||||||
|
*
|
||||||
|
* @struct graph the graph this node exists in
|
||||||
|
* @param[in] data this node's data
|
||||||
|
* @param[in] del data deletion callback
|
||||||
|
* @return the new node
|
||||||
|
*/
|
||||||
|
struct graph_node *
|
||||||
|
graph_new_node (struct graph *graph, void *data, void (*del) (void*));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a node.
|
||||||
|
*
|
||||||
|
* Before deletion, this function removes all edges to and from this node from
|
||||||
|
* any neighbor nodes.
|
||||||
|
*
|
||||||
|
* If, as a result of this operation, any neighbor node has no edges either to
|
||||||
|
* or from itself, that node will be deleted as well. If the graph topology is
|
||||||
|
* e.g. a star this will result in the deletion of all nodes.
|
||||||
|
*
|
||||||
|
* If *data and *del are non-null, the following call is made:
|
||||||
|
* (*node->del) (node->data);
|
||||||
|
*
|
||||||
|
* @param[out] node pointer to node to delete
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
graph_delete_node (struct graph *graph, struct graph_node *node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a directed edge between two nodes.
|
||||||
|
*
|
||||||
|
* @param[in] from
|
||||||
|
* @param[in] to
|
||||||
|
* @return to
|
||||||
|
*/
|
||||||
|
struct graph_node *
|
||||||
|
graph_add_edge (struct graph_node *from, struct graph_node *to);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a graph.
|
||||||
|
*
|
||||||
|
* Calls graph_delete_node on each node before freeing the graph struct itself.
|
||||||
|
*
|
||||||
|
* @param graph the graph to delete
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
graph_delete_graph (struct graph *graph);
|
||||||
|
|
||||||
|
#endif /* _ZEBRA_COMMAND_GRAPH_H */
|
Loading…
Reference in New Issue
Block a user