diff options
author | Tuomas Taipale <tuomas.taipale@nokia.com> | 2022-07-15 08:45:24 +0000 |
---|---|---|
committer | Petri Savolainen <petri.savolainen@nokia.com> | 2022-08-12 13:24:01 +0300 |
commit | 23d2a01295aa6770bb514287c761468c02165cec (patch) | |
tree | bbd6394a53da6e50765dcbc2f5fd68d10891aa8f /helper | |
parent | 9b655bce7b5b9c8a9b62ad4c0c58b13d2671949e (diff) |
helper: cli: add more packet I/O statistics printing commands
Add commands to print packet I/O total, queue, event queue and extra
statistics.
Signed-off-by: Tuomas Taipale <tuomas.taipale@nokia.com>
Reviewed-by: Matias Elo <matias.elo@nokia.com>
Reviewed-by: Jere Leppänen <jere.leppanen@nokia.com>
Diffstat (limited to 'helper')
-rw-r--r-- | helper/cli.c | 417 |
1 files changed, 317 insertions, 100 deletions
diff --git a/helper/cli.c b/helper/cli.c index 0503da230..a514086e2 100644 --- a/helper/cli.c +++ b/helper/cli.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2021, Nokia +/* Copyright (c) 2021-2022, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -17,6 +17,7 @@ #include <poll.h> #include <stdio.h> #include <strings.h> +#include <inttypes.h> /* Socketpair socket roles. */ enum { @@ -195,6 +196,105 @@ static int check_num_args(struct cli_def *cli, int argc, int req_argc) return 0; } +/* Not shared, used only in the server thread. */ +static struct cli_def *cli; +static char *cli_log_fn_buf; + +ODP_PRINTF_FORMAT(2, 0) +static int cli_log_va(odp_log_level_t level, const char *fmt, va_list in_args) +{ + (void)level; + + va_list args; + char *str, *p, *last; + int len; + + /* + * This function should be just a simple call to cli_vabufprint(). + * Unfortunately libcli (at least versions 1.9.7 - 1.10.4) has a few + * bugs. cli_print() prints a newline at the end even if the string + * doesn't end in a newline. cli_*bufprint() on the other hand just + * throws away everything after the last newline. + * + * The following code ensures that each cli_*print() ends in a newline. + * If the string does not end in a newline, we keep the part of the + * string after the last newline and use it the next time we're called. + */ + va_copy(args, in_args); + len = vsnprintf(NULL, 0, fmt, args) + 1; + va_end(args); + str = malloc(len); + + if (!str) { + ODPH_ERR("malloc failed\n"); + return -1; + } + + va_copy(args, in_args); + vsnprintf(str, len, fmt, args); + va_end(args); + p = str; + last = strrchr(p, '\n'); + + if (last) { + *last++ = 0; + if (cli_log_fn_buf) { + cli_bufprint(cli, "%s%s\n", cli_log_fn_buf, p); + free(cli_log_fn_buf); + cli_log_fn_buf = NULL; + } else { + cli_bufprint(cli, "%s\n", p); + } + p = last; + } + + if (*p) { + if (cli_log_fn_buf) { + char *buffer_new = + malloc(strlen(cli_log_fn_buf) + strlen(p) + 1); + + if (!buffer_new) { + ODPH_ERR("malloc failed\n"); + goto out; + } + + strcpy(buffer_new, cli_log_fn_buf); + strcat(buffer_new, p); + free(cli_log_fn_buf); + cli_log_fn_buf = buffer_new; + } else { + cli_log_fn_buf = malloc(strlen(p) + 1); + + if (!cli_log_fn_buf) { + ODPH_ERR("malloc failed\n"); + goto out; + } + + strcpy(cli_log_fn_buf, p); + } + } + +out: + free(str); + + return len; +} + +ODP_PRINTF_FORMAT(2, 3) +static int cli_log(odp_log_level_t level, const char *fmt, ...) +{ + (void)level; + + int r; + va_list args; + + va_start(args, fmt); + r = cli_log_va(level, fmt, args); + va_end(args); + + return r; +} + static int cmd_call_odp_cls_print_all(struct cli_def *cli, const char *command ODP_UNUSED, char *argv[] ODP_UNUSED, int argc) @@ -274,6 +374,25 @@ static int cmd_call_odp_pktio_print(struct cli_def *cli, return CLI_OK; } +static int cmd_call_odp_pktio_extra_stats_print(struct cli_def *cli, + const char *command ODP_UNUSED, + char *argv[], int argc) +{ + if (check_num_args(cli, argc, 1)) + return CLI_ERROR; + + odp_pktio_t hdl = odp_pktio_lookup(argv[0]); + + if (hdl == ODP_PKTIO_INVALID) { + cli_error(cli, "%% Name not found."); + return CLI_ERROR; + } + + odp_pktio_extra_stats_print(hdl); + + return CLI_OK; +} + static int cmd_call_odp_pool_print(struct cli_def *cli, const char *command ODP_UNUSED, char *argv[], int argc) @@ -343,6 +462,191 @@ static int cmd_call_odp_shm_print(struct cli_def *cli, return CLI_OK; } +static int cmd_pktio_stats_print(struct cli_def *cli, const char *command ODP_UNUSED, char *argv[], + int argc) +{ + if (check_num_args(cli, argc, 1)) + return CLI_ERROR; + + odp_pktio_t hdl = odp_pktio_lookup(argv[0]); + + if (hdl == ODP_PKTIO_INVALID) { + cli_error(cli, "%% Name not found."); + return CLI_ERROR; + } + + odp_pktio_stats_t stats; + + if (odp_pktio_stats(hdl, &stats) < 0) { + cli_error(cli, "%% Unable to query stats."); + return CLI_ERROR; + } + + cli_log(ODP_LOG_PRINT, "Pktio statistics\n----------------\n"); + cli_log(ODP_LOG_PRINT, " in_octets: %" PRIu64 "\n", stats.in_octets); + cli_log(ODP_LOG_PRINT, " in_packets: %" PRIu64 "\n", stats.in_packets); + cli_log(ODP_LOG_PRINT, " in_ucast_pkts: %" PRIu64 "\n", stats.in_ucast_pkts); + cli_log(ODP_LOG_PRINT, " in_mcast_pkts: %" PRIu64 "\n", stats.in_mcast_pkts); + cli_log(ODP_LOG_PRINT, " in_bcast_pkts: %" PRIu64 "\n", stats.in_bcast_pkts); + cli_log(ODP_LOG_PRINT, " in_discards: %" PRIu64 "\n", stats.in_discards); + cli_log(ODP_LOG_PRINT, " in_errors: %" PRIu64 "\n", stats.in_errors); + cli_log(ODP_LOG_PRINT, " out_octets: %" PRIu64 "\n", stats.out_octets); + cli_log(ODP_LOG_PRINT, " out_packets: %" PRIu64 "\n", stats.out_packets); + cli_log(ODP_LOG_PRINT, " out_ucast_pkts: %" PRIu64 "\n", stats.out_ucast_pkts); + cli_log(ODP_LOG_PRINT, " out_mcast_pkts: %" PRIu64 "\n", stats.out_mcast_pkts); + cli_log(ODP_LOG_PRINT, " out_bcast_pkts: %" PRIu64 "\n", stats.out_bcast_pkts); + cli_log(ODP_LOG_PRINT, " out_discards: %" PRIu64 "\n", stats.out_discards); + cli_log(ODP_LOG_PRINT, " out_errors: %" PRIu64 "\n\n", stats.out_errors); + + return CLI_OK; +} + +static void cli_log_pktin_queue_stats(odp_pktin_queue_stats_t *stats) +{ + cli_log(ODP_LOG_PRINT, " octets: %" PRIu64 "\n", stats->octets); + cli_log(ODP_LOG_PRINT, " packets: %" PRIu64 "\n", stats->packets); + cli_log(ODP_LOG_PRINT, " discards: %" PRIu64 "\n", stats->discards); + cli_log(ODP_LOG_PRINT, " errors: %" PRIu64 "\n", stats->errors); +} + +static void cli_log_pktout_queue_stats(odp_pktout_queue_stats_t *stats) +{ + cli_log(ODP_LOG_PRINT, " octets: %" PRIu64 "\n", stats->octets); + cli_log(ODP_LOG_PRINT, " packets: %" PRIu64 "\n", stats->packets); + cli_log(ODP_LOG_PRINT, " discards: %" PRIu64 "\n", stats->discards); + cli_log(ODP_LOG_PRINT, " errors: %" PRIu64 "\n", stats->errors); +} + +static int cmd_pktio_queue_stats_print(struct cli_def *cli, const char *command ODP_UNUSED, + char *argv[], int argc) +{ + if (check_num_args(cli, argc, 1)) + return CLI_ERROR; + + odp_pktio_t hdl = odp_pktio_lookup(argv[0]); + + if (hdl == ODP_PKTIO_INVALID) { + cli_error(cli, "%% Name not found."); + return CLI_ERROR; + } + + int in_q_cnt = odp_pktin_queue(hdl, NULL, 0); + + if (in_q_cnt > 0) { + odp_pktin_queue_t in_qs[in_q_cnt]; + odp_pktin_queue_stats_t in_stats; + + in_q_cnt = odp_pktin_queue(hdl, in_qs, in_q_cnt); + + cli_log(ODP_LOG_PRINT, "Pktin queue statistics\n----------------------\n"); + + for (int i = 0; i < in_q_cnt; i++) { + cli_log(ODP_LOG_PRINT, "Pktin queue: %d:\n", i); + + if (odp_pktin_queue_stats(in_qs[i], &in_stats) < 0) { + cli_log(ODP_LOG_PRINT, + " (Unable to read statistics, skipping)\n"); + continue; + } + + cli_log_pktin_queue_stats(&in_stats); + } + } + + int out_q_cnt = odp_pktout_queue(hdl, NULL, 0); + + if (out_q_cnt > 0) { + odp_pktout_queue_t out_qs[out_q_cnt]; + odp_pktout_queue_stats_t out_stats; + + out_q_cnt = odp_pktout_queue(hdl, out_qs, out_q_cnt); + + cli_log(ODP_LOG_PRINT, "Pktout queue statistics\n-----------------------\n"); + + for (int i = 0; i < out_q_cnt; i++) { + cli_log(ODP_LOG_PRINT, "Pktout queue: %d:\n", i); + + if (odp_pktout_queue_stats(out_qs[i], &out_stats) < 0) { + cli_log(ODP_LOG_PRINT, + " (Unable to read statistics, skipping)\n"); + continue; + } + + cli_log_pktout_queue_stats(&out_stats); + } + } + + cli_log(ODP_LOG_PRINT, "\n"); + + return CLI_OK; +} + +static int cmd_pktio_event_queue_stats_print(struct cli_def *cli, const char *command ODP_UNUSED, + char *argv[], int argc) +{ + if (check_num_args(cli, argc, 1)) + return CLI_ERROR; + + odp_pktio_t hdl = odp_pktio_lookup(argv[0]); + + if (hdl == ODP_PKTIO_INVALID) { + cli_error(cli, "%% Name not found."); + return CLI_ERROR; + } + + int in_q_cnt = odp_pktin_event_queue(hdl, NULL, 0); + + if (in_q_cnt > 0) { + odp_queue_t in_qs[in_q_cnt]; + odp_pktin_queue_stats_t in_stats; + + in_q_cnt = odp_pktin_event_queue(hdl, in_qs, in_q_cnt); + + cli_log(ODP_LOG_PRINT, + "Pktin event queue statistics\n----------------------------\n"); + + for (int i = 0; i < in_q_cnt; i++) { + cli_log(ODP_LOG_PRINT, "Pktin event queue: %d:\n", i); + + if (odp_pktin_event_queue_stats(hdl, in_qs[i], &in_stats) < 0) { + cli_log(ODP_LOG_PRINT, + " (Unable to read statistics, skipping)\n"); + continue; + } + + cli_log_pktin_queue_stats(&in_stats); + } + } + + int out_q_cnt = odp_pktout_event_queue(hdl, NULL, 0); + + if (out_q_cnt > 0) { + odp_queue_t out_qs[out_q_cnt]; + odp_pktout_queue_stats_t out_stats; + + out_q_cnt = odp_pktout_event_queue(hdl, out_qs, out_q_cnt); + + cli_log(ODP_LOG_PRINT, + "Pktout event queue statistics\n-----------------------------\n"); + + for (int i = 0; i < out_q_cnt; i++) { + cli_log(ODP_LOG_PRINT, "Pktout event queue: %d:\n", i); + + if (odp_pktout_event_queue_stats(hdl, out_qs[i], &out_stats) < 0) { + cli_log(ODP_LOG_PRINT, + " (Unable to read statistics, skipping)\n"); + continue; + } + + cli_log_pktout_queue_stats(&out_stats); + } + } + + cli_log(ODP_LOG_PRINT, "\n"); + + return CLI_OK; +} + static int cmd_user_cmd(struct cli_def *cli ODP_UNUSED, const char *command, char *argv[], int argc) { @@ -384,6 +688,9 @@ static struct cli_def *create_cli(cli_shm_t *shm) cli_register_command(cli, c, "odp_pktio_print", cmd_call_odp_pktio_print, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "<name>"); + cli_register_command(cli, c, "odp_pktio_extra_stats_print", + cmd_call_odp_pktio_extra_stats_print, + PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "<name>"); cli_register_command(cli, c, "odp_pool_print", cmd_call_odp_pool_print, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "<name>"); @@ -405,6 +712,15 @@ static struct cli_def *create_cli(cli_shm_t *shm) cli_register_command(cli, c, "odp_sys_info_print", cmd_call_odp_sys_info_print, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); + cli_register_command(cli, NULL, "pktio_stats_print", + cmd_pktio_stats_print, + PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "<name>"); + cli_register_command(cli, NULL, "pktio_queue_stats_print", + cmd_pktio_queue_stats_print, + PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "<name>"); + cli_register_command(cli, NULL, "pktio_event_queue_stats_print", + cmd_pktio_event_queue_stats_print, + PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "<name>"); for (uint32_t i = 0; i < shm->num_user_commands; i++) { cli_register_command(cli, NULL, shm->user_cmd[i].name, @@ -415,105 +731,6 @@ static struct cli_def *create_cli(cli_shm_t *shm) return cli; } -/* Not shared, used only in the server thread. */ -static struct cli_def *cli; -static char *cli_log_fn_buf; - -ODP_PRINTF_FORMAT(2, 0) -static int cli_log_va(odp_log_level_t level, const char *fmt, va_list in_args) -{ - (void)level; - - va_list args; - char *str, *p, *last; - int len; - - /* - * This function should be just a simple call to cli_vabufprint(). - * Unfortunately libcli (at least versions 1.9.7 - 1.10.4) has a few - * bugs. cli_print() prints a newline at the end even if the string - * doesn't end in a newline. cli_*bufprint() on the other hand just - * throws away everything after the last newline. - * - * The following code ensures that each cli_*print() ends in a newline. - * If the string does not end in a newline, we keep the part of the - * string after the last newline and use it the next time we're called. - */ - va_copy(args, in_args); - len = vsnprintf(NULL, 0, fmt, args) + 1; - va_end(args); - str = malloc(len); - - if (!str) { - ODPH_ERR("malloc failed\n"); - return -1; - } - - va_copy(args, in_args); - vsnprintf(str, len, fmt, args); - va_end(args); - p = str; - last = strrchr(p, '\n'); - - if (last) { - *last++ = 0; - if (cli_log_fn_buf) { - cli_bufprint(cli, "%s%s\n", cli_log_fn_buf, p); - free(cli_log_fn_buf); - cli_log_fn_buf = NULL; - } else { - cli_bufprint(cli, "%s\n", p); - } - p = last; - } - - if (*p) { - if (cli_log_fn_buf) { - char *buffer_new = - malloc(strlen(cli_log_fn_buf) + strlen(p) + 1); - - if (!buffer_new) { - ODPH_ERR("malloc failed\n"); - goto out; - } - - strcpy(buffer_new, cli_log_fn_buf); - strcat(buffer_new, p); - free(cli_log_fn_buf); - cli_log_fn_buf = buffer_new; - } else { - cli_log_fn_buf = malloc(strlen(p) + 1); - - if (!cli_log_fn_buf) { - ODPH_ERR("malloc failed\n"); - goto out; - } - - strcpy(cli_log_fn_buf, p); - } - } - -out: - free(str); - - return len; -} - -ODP_PRINTF_FORMAT(2, 3) -static int cli_log(odp_log_level_t level, const char *fmt, ...) -{ - (void)level; - - int r; - va_list args; - - va_start(args, fmt); - r = cli_log_va(level, fmt, args); - va_end(args); - - return r; -} - ODP_PRINTF_FORMAT(1, 2) int odph_cli_log(const char *fmt, ...) { |