diff options
Diffstat (limited to 'helper/cli.c')
-rw-r--r-- | helper/cli.c | 531 |
1 files changed, 374 insertions, 157 deletions
diff --git a/helper/cli.c b/helper/cli.c index 0503da230..fef42ec61 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,9 +196,120 @@ static int check_num_args(struct cli_def *cli, int argc, int req_argc) return 0; } -static int cmd_call_odp_cls_print_all(struct cli_def *cli, - const char *command ODP_UNUSED, - char *argv[] ODP_UNUSED, int argc) +/* 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 = NULL, *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); + va_end(args); + + if (len < 0) { + ODPH_ERR("vsnprintf failed\n"); + goto out; + } + + len++; + str = malloc(len); + + if (!str) { + ODPH_ERR("malloc failed\n"); + return -1; + } + + va_copy(args, in_args); + len = vsnprintf(str, len, fmt, args); + va_end(args); + + if (len < 0) { + ODPH_ERR("vsnprintf failed\n"); + goto out; + } + + 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_odp_cls_print_all(struct cli_def *cli, const char *command ODP_UNUSED, + char *argv[] ODP_UNUSED, int argc) { if (check_num_args(cli, argc, 0)) return CLI_ERROR; @@ -207,9 +319,8 @@ static int cmd_call_odp_cls_print_all(struct cli_def *cli, return CLI_OK; } -static int cmd_call_odp_ipsec_print(struct cli_def *cli, - const char *command ODP_UNUSED, - char *argv[] ODP_UNUSED, int argc) +static int cmd_odp_ipsec_print(struct cli_def *cli, const char *command ODP_UNUSED, + char *argv[] ODP_UNUSED, int argc) { if (check_num_args(cli, argc, 0)) return CLI_ERROR; @@ -219,9 +330,8 @@ static int cmd_call_odp_ipsec_print(struct cli_def *cli, return CLI_OK; } -static int cmd_call_odp_shm_print_all(struct cli_def *cli, - const char *command ODP_UNUSED, - char *argv[] ODP_UNUSED, int argc) +static int cmd_odp_shm_print_all(struct cli_def *cli, const char *command ODP_UNUSED, + char *argv[] ODP_UNUSED, int argc) { if (check_num_args(cli, argc, 0)) return CLI_ERROR; @@ -231,9 +341,8 @@ static int cmd_call_odp_shm_print_all(struct cli_def *cli, return CLI_OK; } -static int cmd_call_odp_sys_config_print(struct cli_def *cli, - const char *command ODP_UNUSED, - char *argv[] ODP_UNUSED, int argc) +static int cmd_odp_sys_config_print(struct cli_def *cli, const char *command ODP_UNUSED, + char *argv[] ODP_UNUSED, int argc) { if (check_num_args(cli, argc, 0)) return CLI_ERROR; @@ -243,9 +352,8 @@ static int cmd_call_odp_sys_config_print(struct cli_def *cli, return CLI_OK; } -static int cmd_call_odp_sys_info_print(struct cli_def *cli, - const char *command ODP_UNUSED, - char *argv[] ODP_UNUSED, int argc) +static int cmd_odp_sys_info_print(struct cli_def *cli, const char *command ODP_UNUSED, + char *argv[] ODP_UNUSED, int argc) { if (check_num_args(cli, argc, 0)) return CLI_ERROR; @@ -255,9 +363,8 @@ static int cmd_call_odp_sys_info_print(struct cli_def *cli, return CLI_OK; } -static int cmd_call_odp_pktio_print(struct cli_def *cli, - const char *command ODP_UNUSED, - char *argv[], int argc) +static int cmd_odp_pktio_print(struct cli_def *cli, const char *command ODP_UNUSED, char *argv[], + int argc) { if (check_num_args(cli, argc, 1)) return CLI_ERROR; @@ -274,9 +381,38 @@ static int cmd_call_odp_pktio_print(struct cli_def *cli, return CLI_OK; } -static int cmd_call_odp_pool_print(struct cli_def *cli, - const char *command ODP_UNUSED, char *argv[], - int argc) +static int cmd_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_odp_pool_print_all(struct cli_def *cli, + const char *command ODP_UNUSED, + char *argv[] ODP_UNUSED, int argc) +{ + if (check_num_args(cli, argc, 0)) + return CLI_ERROR; + + odp_pool_print_all(); + + return CLI_OK; +} + +static int cmd_odp_pool_print(struct cli_def *cli, const char *command ODP_UNUSED, char *argv[], + int argc) { if (check_num_args(cli, argc, 1)) return CLI_ERROR; @@ -293,9 +429,8 @@ static int cmd_call_odp_pool_print(struct cli_def *cli, return CLI_OK; } -static int cmd_call_odp_queue_print(struct cli_def *cli, - const char *command ODP_UNUSED, - char *argv[], int argc) +static int cmd_odp_queue_print(struct cli_def *cli, const char *command ODP_UNUSED, char *argv[], + int argc) { if (check_num_args(cli, argc, 1)) return CLI_ERROR; @@ -312,9 +447,8 @@ static int cmd_call_odp_queue_print(struct cli_def *cli, return CLI_OK; } -static int cmd_call_odp_queue_print_all(struct cli_def *cli, - const char *command ODP_UNUSED, - char *argv[] ODP_UNUSED, int argc) +static int cmd_odp_queue_print_all(struct cli_def *cli, const char *command ODP_UNUSED, + char *argv[] ODP_UNUSED, int argc) { if (check_num_args(cli, argc, 0)) return CLI_ERROR; @@ -324,9 +458,19 @@ static int cmd_call_odp_queue_print_all(struct cli_def *cli, return CLI_OK; } -static int cmd_call_odp_shm_print(struct cli_def *cli, - const char *command ODP_UNUSED, char *argv[], - int argc) +static int cmd_odp_schedule_print(struct cli_def *cli, const char *command ODP_UNUSED, + char *argv[] ODP_UNUSED, int argc) +{ + if (check_num_args(cli, argc, 0)) + return CLI_ERROR; + + odp_schedule_print(); + + return CLI_OK; +} + +static int cmd_odp_shm_print(struct cli_def *cli, const char *command ODP_UNUSED, char *argv[], + int argc) { if (check_num_args(cli, argc, 1)) return CLI_ERROR; @@ -343,175 +487,248 @@ static int cmd_call_odp_shm_print(struct cli_def *cli, return CLI_OK; } -static int cmd_user_cmd(struct cli_def *cli ODP_UNUSED, const char *command, - char *argv[], int argc) +static int cmd_odp_pktio_stats_print(struct cli_def *cli, const char *command ODP_UNUSED, + char *argv[], int argc) { - cli_shm_t *shm = shm_lookup(); + if (check_num_args(cli, argc, 1)) + return CLI_ERROR; - if (!shm) { - ODPH_ERR("Error: shm %s not found\n", shm_name); + odp_pktio_t hdl = odp_pktio_lookup(argv[0]); + + if (hdl == ODP_PKTIO_INVALID) { + cli_error(cli, "%% Name not found."); return CLI_ERROR; } - for (uint32_t i = 0; i < shm->num_user_commands; i++) { - if (!strcasecmp(command, shm->user_cmd[i].name)) { - shm->user_cmd[i].fn(argc, argv); - break; - } + 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 struct cli_def *create_cli(cli_shm_t *shm) +static void cli_log_pktin_queue_stats(odp_pktin_queue_stats_t *stats) { - struct cli_command *c; - struct cli_def *cli; + 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); +} - cli = cli_init(); - cli_set_banner(cli, NULL); - cli_set_hostname(cli, shm->cli_param.hostname); +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); +} - c = cli_register_command(cli, NULL, "call", NULL, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, - "Call ODP API function."); - cli_register_command(cli, c, "odp_cls_print_all", - cmd_call_odp_cls_print_all, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); - cli_register_command(cli, c, "odp_ipsec_print", - cmd_call_odp_ipsec_print, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); - cli_register_command(cli, c, "odp_pktio_print", - cmd_call_odp_pktio_print, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "<name>"); - cli_register_command(cli, c, "odp_pool_print", - cmd_call_odp_pool_print, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "<name>"); - cli_register_command(cli, c, "odp_queue_print", - cmd_call_odp_queue_print, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "<name>"); - cli_register_command(cli, c, "odp_queue_print_all", - cmd_call_odp_queue_print_all, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); - cli_register_command(cli, c, "odp_shm_print_all", - cmd_call_odp_shm_print_all, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); - cli_register_command(cli, c, "odp_shm_print", - cmd_call_odp_shm_print, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "<name>"); - cli_register_command(cli, c, "odp_sys_config_print", - cmd_call_odp_sys_config_print, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); - cli_register_command(cli, c, "odp_sys_info_print", - cmd_call_odp_sys_info_print, - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); +static int cmd_odp_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; - for (uint32_t i = 0; i < shm->num_user_commands; i++) { - cli_register_command(cli, NULL, shm->user_cmd[i].name, - cmd_user_cmd, PRIVILEGE_UNPRIVILEGED, - MODE_EXEC, shm->user_cmd[i].help); + odp_pktio_t hdl = odp_pktio_lookup(argv[0]); + + if (hdl == ODP_PKTIO_INVALID) { + cli_error(cli, "%% Name not found."); + return CLI_ERROR; } - return cli; -} + int in_q_cnt = odp_pktin_queue(hdl, NULL, 0); -/* Not shared, used only in the server thread. */ -static struct cli_def *cli; -static char *cli_log_fn_buf; + if (in_q_cnt > 0) { + odp_pktin_queue_t in_qs[in_q_cnt]; + odp_pktin_queue_stats_t in_stats; -ODP_PRINTF_FORMAT(2, 0) -static int cli_log_va(odp_log_level_t level, const char *fmt, va_list in_args) -{ - (void)level; + in_q_cnt = odp_pktin_queue(hdl, in_qs, in_q_cnt); - va_list args; - char *str, *p, *last; - int len; + cli_log(ODP_LOG_PRINT, "Pktin queue statistics\n----------------------\n"); - /* - * 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); + for (int i = 0; i < in_q_cnt; i++) { + cli_log(ODP_LOG_PRINT, "Pktin queue: %d:\n", i); - if (!str) { - ODPH_ERR("malloc failed\n"); - return -1; + 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); + } } - va_copy(args, in_args); - vsnprintf(str, len, fmt, args); - va_end(args); - p = str; - last = strrchr(p, '\n'); + int out_q_cnt = odp_pktout_queue(hdl, NULL, 0); - 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); + 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); } - p = last; } - if (*p) { - if (cli_log_fn_buf) { - char *buffer_new = - malloc(strlen(cli_log_fn_buf) + strlen(p) + 1); + cli_log(ODP_LOG_PRINT, "\n"); - if (!buffer_new) { - ODPH_ERR("malloc failed\n"); - goto out; + return CLI_OK; +} + +static int cmd_odp_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; } - 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); + cli_log_pktin_queue_stats(&in_stats); + } + } - if (!cli_log_fn_buf) { - ODPH_ERR("malloc failed\n"); - goto out; + 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; } - strcpy(cli_log_fn_buf, p); + cli_log_pktout_queue_stats(&out_stats); } } -out: - free(str); + cli_log(ODP_LOG_PRINT, "\n"); - return len; + return CLI_OK; } -ODP_PRINTF_FORMAT(2, 3) -static int cli_log(odp_log_level_t level, const char *fmt, ...) +static int cmd_user_cmd(struct cli_def *cli ODP_UNUSED, const char *command, + char *argv[], int argc) { - (void)level; + cli_shm_t *shm = shm_lookup(); - int r; - va_list args; + if (!shm) { + ODPH_ERR("Error: shm %s not found\n", shm_name); + return CLI_ERROR; + } - va_start(args, fmt); - r = cli_log_va(level, fmt, args); - va_end(args); + for (uint32_t i = 0; i < shm->num_user_commands; i++) { + if (!strcasecmp(command, shm->user_cmd[i].name)) { + shm->user_cmd[i].fn(argc, argv); + break; + } + } - return r; + return CLI_OK; +} + +static struct cli_def *create_cli(cli_shm_t *shm) +{ + struct cli_def *cli; + + cli = cli_init(); + cli_set_banner(cli, NULL); + cli_set_hostname(cli, shm->cli_param.hostname); + +#define CMD(name, help) \ + cli_register_command(cli, NULL, #name, cmd_ ## name, \ + PRIVILEGE_UNPRIVILEGED, MODE_EXEC, help) + + CMD(odp_cls_print_all, NULL); + CMD(odp_ipsec_print, NULL); + CMD(odp_pktio_event_queue_stats_print, "<name>"); + CMD(odp_pktio_extra_stats_print, "<name>"); + CMD(odp_pktio_print, "<name>"); + CMD(odp_pktio_queue_stats_print, "<name>"); + CMD(odp_pktio_stats_print, "<name>"); + CMD(odp_pool_print_all, NULL); + CMD(odp_pool_print, "<name>"); + CMD(odp_queue_print_all, NULL); + CMD(odp_queue_print, "<name>"); + CMD(odp_schedule_print, NULL); + CMD(odp_shm_print_all, NULL); + CMD(odp_shm_print, "<name>"); + CMD(odp_sys_config_print, NULL); + CMD(odp_sys_info_print, NULL); + + for (uint32_t i = 0; i < shm->num_user_commands; i++) { + cli_register_command(cli, NULL, shm->user_cmd[i].name, + cmd_user_cmd, PRIVILEGE_UNPRIVILEGED, + MODE_EXEC, shm->user_cmd[i].help); + } + + return cli; } ODP_PRINTF_FORMAT(1, 2) |