diff options
author | Benoît Ganne <bganne@cisco.com> | 2019-01-21 17:41:25 +0100 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2019-01-31 22:08:54 +0000 |
commit | 362456a9bdc5ffc440bf776c3685ba81b8513f6e (patch) | |
tree | db06209bef7bd0fbf5dceb94c2126a782f369040 | |
parent | 35467f112acb21fe1ea287c7d8794b0859f149c0 (diff) |
Add 'show vlib graphviz' command
Add a new command to dump vlib graph as graphviz/dot file
Change-Id: I43fc072cff8153ac500e5fbc6641a3705c2e995e
Signed-off-by: Benoît Ganne <bganne@cisco.com>
-rw-r--r-- | src/vlib/format.c | 24 | ||||
-rw-r--r-- | src/vlib/format_funcs.h | 3 | ||||
-rw-r--r-- | src/vlib/main.c | 19 | ||||
-rw-r--r-- | src/vlib/node_cli.c | 78 |
4 files changed, 108 insertions, 16 deletions
diff --git a/src/vlib/format.c b/src/vlib/format.c index 79a4d6866db..ee730bd1c28 100644 --- a/src/vlib/format.c +++ b/src/vlib/format.c @@ -187,6 +187,30 @@ done: return p != 0; } +/* Parse a filename to dump debug info */ +uword +unformat_vlib_tmpfile (unformat_input_t * input, va_list * args) +{ + u8 **chroot_filename = va_arg (*args, u8 **); + u8 *filename; + + if (!unformat (input, "%s", &filename)) + return 0; + + /* Brain-police user path input */ + if (strstr ((char *) filename, "..") || index ((char *) filename, '/')) + { + vec_free (filename); + return 0; + } + + *chroot_filename = format (0, "/tmp/%s%c", filename, 0); + vec_free (filename); + + return 1; +} + + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vlib/format_funcs.h b/src/vlib/format_funcs.h index f60b8940d14..30e919d7e96 100644 --- a/src/vlib/format_funcs.h +++ b/src/vlib/format_funcs.h @@ -59,6 +59,9 @@ uword unformat_vlib_number_by_name (unformat_input_t * input, va_list * args); /* Parse an int either %d or 0x%x. */ uword unformat_vlib_number (unformat_input_t * input, va_list * args); +/* Parse a filename to dump debug info */ +uword unformat_vlib_tmpfile (unformat_input_t * input, va_list * args); + /* Flag to format_vlib_*_header functions to tell them not to recurse into the next layer's header. For example, tells format_vlib_ethernet_header not to format ip header. */ diff --git a/src/vlib/main.c b/src/vlib/main.c index c0ab8e129b9..c5153abc0cc 100644 --- a/src/vlib/main.c +++ b/src/vlib/main.c @@ -2126,7 +2126,9 @@ pcap_dispatch_trace_command_internal (vlib_main_t * vm, } pm->n_packets_to_capture = max; } - else if (unformat (line_input, "file %s", &filename)) + else + if (unformat + (line_input, "file %U", unformat_vlib_tmpfile, &filename)) { if (vm->dispatch_pcap_enable) { @@ -2135,21 +2137,6 @@ pcap_dispatch_trace_command_internal (vlib_main_t * vm, errorFlag = 1; break; } - - /* Brain-police user path input */ - if (strstr ((char *) filename, "..") - || index ((char *) filename, '/')) - { - vlib_cli_output (vm, "illegal characters in filename '%s'", - filename); - vlib_cli_output (vm, "Hint: .. and / are not allowed."); - vec_free (filename); - errorFlag = 1; - break; - } - - chroot_filename = format (0, "/tmp/%s%c", filename, 0); - vec_free (filename); } else if (unformat (line_input, "status")) { diff --git a/src/vlib/node_cli.c b/src/vlib/node_cli.c index ad17c1d6f4d..c8e32b58a69 100644 --- a/src/vlib/node_cli.c +++ b/src/vlib/node_cli.c @@ -37,6 +37,9 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> #include <vlib/vlib.h> #include <vlib/threads.h> @@ -88,6 +91,81 @@ VLIB_CLI_COMMAND (show_node_graph_command, static) = { }; /* *INDENT-ON* */ +static clib_error_t * +show_node_graphviz (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + clib_error_t *error = 0; + vlib_node_main_t *nm = &vm->node_main; + u8 *chroot_filename = 0; + int fd; + vlib_node_t **nodes = 0; + uword i, j; + + if (!unformat_user (input, unformat_vlib_tmpfile, &chroot_filename)) + { + fd = -1; + } + else + { + fd = + open ((char *) chroot_filename, O_CREAT | O_TRUNC | O_WRONLY, 0664); + } + +#define format__(vm__, fd__, ...) \ + if ((fd) < 0) \ + { \ + vlib_cli_output((vm__), ## __VA_ARGS__); \ + } \ + else \ + { \ + fdformat((fd__), ## __VA_ARGS__); \ + } + + format__ (vm, fd, "%s", "digraph {\n"); + + nodes = vec_dup (nm->nodes); + vec_sort_with_function (nodes, node_cmp); + + for (i = 0; i < vec_len (nodes); i++) + { + for (j = 0; j < vec_len (nodes[i]->next_nodes); j++) + { + vlib_node_t *x; + + if (nodes[i]->next_nodes[j] == VLIB_INVALID_NODE_INDEX) + continue; + + x = vec_elt (nm->nodes, nodes[i]->next_nodes[j]); + format__ (vm, fd, " \"%v\" -> \"%v\"\n", nodes[i]->name, x->name); + } + } + + format__ (vm, fd, "%s", "}"); + + if (fd >= 0) + { + vlib_cli_output (vm, + "vlib graph dumped into `%s'. Run eg. `fdp -Tsvg -O %s'.", + chroot_filename, chroot_filename); + } + + vec_free (nodes); + vec_free (chroot_filename); + vec_free (nodes); + if (fd >= 0) + close (fd); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (show_node_graphviz_command, static) = { + .path = "show vlib graphviz", + .short_help = "Dump packet processing node graph as a graphviz dotfile", + .function = show_node_graphviz, +}; +/* *INDENT-ON* */ + static u8 * format_vlib_node_state (u8 * s, va_list * va) { |