aboutsummaryrefslogtreecommitdiff
path: root/helper
diff options
context:
space:
mode:
authorTuomas Taipale <tuomas.taipale@nokia.com>2022-07-15 08:45:24 +0000
committerPetri Savolainen <petri.savolainen@nokia.com>2022-08-12 13:24:01 +0300
commit23d2a01295aa6770bb514287c761468c02165cec (patch)
treebbd6394a53da6e50765dcbc2f5fd68d10891aa8f /helper
parent9b655bce7b5b9c8a9b62ad4c0c58b13d2671949e (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.c417
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, ...)
{