From: Intel Date: Wed, 18 Sep 2013 10:00:00 +0000 (+0200) Subject: examples/qos_sched: add stats X-Git-Tag: spdx-start~11110 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=cfd5c971e5e70995bf2d30d74ed2f12d52c999bd;p=dpdk.git examples/qos_sched: add stats Signed-off-by: Intel --- diff --git a/examples/qos_sched/Makefile b/examples/qos_sched/Makefile index 31ee7a4c3e..5e634c722f 100755 --- a/examples/qos_sched/Makefile +++ b/examples/qos_sched/Makefile @@ -47,7 +47,7 @@ endif APP = qos_sched # all source are stored in SRCS-y -SRCS-y := main.c args.c init.c app_thread.c cfg_file.c +SRCS-y := main.c args.c init.c app_thread.c cfg_file.c cmdline.c stats.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) diff --git a/examples/qos_sched/args.c b/examples/qos_sched/args.c index 9dc5f5affe..9b0fbd72db 100755 --- a/examples/qos_sched/args.c +++ b/examples/qos_sched/args.c @@ -68,6 +68,7 @@ static const char usage[] = " multiple pfc can be configured in command line \n" " \n" "Application optional parameters: \n" + " --i : run in interactive mode (default value is %u) \n" " --mst I : master core index (default value is %u) \n" " --rsz \"A, B, C\" : Ring sizes \n" " A = Size (in number of buffer descriptors) of each of the NIC RX \n" @@ -100,7 +101,7 @@ static const char usage[] = static void app_usage(const char *prgname) { - printf(usage, prgname, app_master_core, + printf(usage, prgname, APP_INTERACTIVE_DEFAULT, app_master_core, APP_RX_DESC_DEFAULT, APP_RING_SIZE, APP_TX_DESC_DEFAULT, MAX_PKT_RX_BURST, PKT_ENQUEUE, PKT_DEQUEUE, MAX_PKT_TX_BURST, NB_MBUF, @@ -355,10 +356,14 @@ app_parse_args(int argc, char **argv) /* set en_US locale to print big numbers with ',' */ setlocale(LC_NUMERIC, "en_US.utf-8"); - while ((opt = getopt_long(argc, argv, "", + while ((opt = getopt_long(argc, argv, "i", lgopts, &option_index)) != EOF) { switch (opt) { + case 'i': + printf("Interactive-mode selected\n"); + interactive = 1; + break; /* long options */ case 0: optname = lgopts[option_index].name; diff --git a/examples/qos_sched/cmdline.c b/examples/qos_sched/cmdline.c new file mode 100644 index 0000000000..151ca148a2 --- /dev/null +++ b/examples/qos_sched/cmdline.c @@ -0,0 +1,643 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "main.h" + +/* *** Help command with introduction. *** */ +struct cmd_help_result { + cmdline_fixed_string_t help; +}; + +static void cmd_help_parsed(__attribute__((unused)) void *parsed_result, + struct cmdline *cl, + __attribute__((unused)) void *data) +{ + cmdline_printf( + cl, + "\n" + "The following commands are currently available:\n\n" + "Control:\n" + " quit : Quit the application.\n" + "\nStatistics:\n" + " stats app : Show app statistics.\n" + " stats port X subport Y : Show stats of a specific subport.\n" + " stats port X subport Y pipe Z : Show stats of a specific pipe.\n" + "\nAverage queue size:\n" + " qavg port X subport Y : Show average queue size per subport.\n" + " qavg port X subport Y tc Z : Show average queue size per subport and TC.\n" + " qavg port X subport Y pipe Z : Show average queue size per pipe.\n" + " qavg port X subport Y pipe Z tc A : Show average queue size per pipe and TC.\n" + " qavg port X subport Y pipe Z tc A q B : Show average queue size of a specific queue.\n" + " qavg [n|period] X : Set number of times and peiod (us).\n\n" + ); + +} + +cmdline_parse_token_string_t cmd_help_help = + TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); + +cmdline_parse_inst_t cmd_help = { + .f = cmd_help_parsed, + .data = NULL, + .help_str = "show help", + .tokens = { + (void *)&cmd_help_help, + NULL, + }, +}; + +/* *** QUIT *** */ +struct cmd_quit_result { + cmdline_fixed_string_t quit; +}; + +static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, + struct cmdline *cl, + __attribute__((unused)) void *data) +{ + cmdline_quit(cl); +} + +cmdline_parse_token_string_t cmd_quit_quit = + TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); + +cmdline_parse_inst_t cmd_quit = { + .f = cmd_quit_parsed, + .data = NULL, + .help_str = "exit application", + .tokens = { + (void *)&cmd_quit_quit, + NULL, + }, +}; + +/* *** SET QAVG PARAMETERS *** */ +struct cmd_setqavg_result { + cmdline_fixed_string_t qavg_string; + cmdline_fixed_string_t param_string; + uint32_t number; +}; + +static void cmd_setqavg_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_setqavg_result *res = parsed_result; + + if (!strcmp(res->param_string, "period")) + qavg_period = res->number; + else if (!strcmp(res->param_string, "n")) + qavg_ntimes = res->number; + else + printf("\nUnknown parameter.\n\n"); +} + +cmdline_parse_token_string_t cmd_setqavg_qavg_string = + TOKEN_STRING_INITIALIZER(struct cmd_setqavg_result, qavg_string, + "qavg"); +cmdline_parse_token_string_t cmd_setqavg_param_string = + TOKEN_STRING_INITIALIZER(struct cmd_setqavg_result, param_string, + "period#n"); +cmdline_parse_token_num_t cmd_setqavg_number = + TOKEN_NUM_INITIALIZER(struct cmd_setqavg_result, number, + UINT32); + +cmdline_parse_inst_t cmd_setqavg = { + .f = cmd_setqavg_parsed, + .data = NULL, + .help_str = "Show subport stats.", + .tokens = { + (void *)&cmd_setqavg_qavg_string, + (void *)&cmd_setqavg_param_string, + (void *)&cmd_setqavg_number, + NULL, + }, +}; + +/* *** SHOW APP STATS *** */ +struct cmd_appstats_result { + cmdline_fixed_string_t stats_string; + cmdline_fixed_string_t app_string; +}; + +static void cmd_appstats_parsed(__attribute__((unused)) void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + app_stat(); +} + +cmdline_parse_token_string_t cmd_appstats_stats_string = + TOKEN_STRING_INITIALIZER(struct cmd_appstats_result, stats_string, + "stats"); +cmdline_parse_token_string_t cmd_appstats_app_string = + TOKEN_STRING_INITIALIZER(struct cmd_appstats_result, app_string, + "app"); + +cmdline_parse_inst_t cmd_appstats = { + .f = cmd_appstats_parsed, + .data = NULL, + .help_str = "Show app stats.", + .tokens = { + (void *)&cmd_appstats_stats_string, + (void *)&cmd_appstats_app_string, + NULL, + }, +}; + +/* *** SHOW SUBPORT STATS *** */ +struct cmd_subportstats_result { + cmdline_fixed_string_t stats_string; + cmdline_fixed_string_t port_string; + uint8_t port_number; + cmdline_fixed_string_t subport_string; + uint32_t subport_number; +}; + +static void cmd_subportstats_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_subportstats_result *res = parsed_result; + + if (subport_stat(res->port_number, res->subport_number) < 0) + printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); +} + +cmdline_parse_token_string_t cmd_subportstats_stats_string = + TOKEN_STRING_INITIALIZER(struct cmd_subportstats_result, stats_string, + "stats"); +cmdline_parse_token_string_t cmd_subportstats_port_string = + TOKEN_STRING_INITIALIZER(struct cmd_subportstats_result, port_string, + "port"); +cmdline_parse_token_string_t cmd_subportstats_subport_string = + TOKEN_STRING_INITIALIZER(struct cmd_subportstats_result, subport_string, + "subport"); +cmdline_parse_token_num_t cmd_subportstats_subport_number = + TOKEN_NUM_INITIALIZER(struct cmd_subportstats_result, subport_number, + UINT32); +cmdline_parse_token_num_t cmd_subportstats_port_number = + TOKEN_NUM_INITIALIZER(struct cmd_subportstats_result, port_number, + UINT8); + +cmdline_parse_inst_t cmd_subportstats = { + .f = cmd_subportstats_parsed, + .data = NULL, + .help_str = "Show subport stats.", + .tokens = { + (void *)&cmd_subportstats_stats_string, + (void *)&cmd_subportstats_port_string, + (void *)&cmd_subportstats_port_number, + (void *)&cmd_subportstats_subport_string, + (void *)&cmd_subportstats_subport_number, + NULL, + }, +}; + +/* *** SHOW PIPE STATS *** */ +struct cmd_pipestats_result { + cmdline_fixed_string_t stats_string; + cmdline_fixed_string_t port_string; + uint8_t port_number; + cmdline_fixed_string_t subport_string; + uint32_t subport_number; + cmdline_fixed_string_t pipe_string; + uint32_t pipe_number; +}; + +static void cmd_pipestats_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_pipestats_result *res = parsed_result; + + if (pipe_stat(res->port_number, res->subport_number, res->pipe_number) < 0) + printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); +} + +cmdline_parse_token_string_t cmd_pipestats_stats_string = + TOKEN_STRING_INITIALIZER(struct cmd_pipestats_result, stats_string, + "stats"); +cmdline_parse_token_string_t cmd_pipestats_port_string = + TOKEN_STRING_INITIALIZER(struct cmd_pipestats_result, port_string, + "port"); +cmdline_parse_token_num_t cmd_pipestats_port_number = + TOKEN_NUM_INITIALIZER(struct cmd_pipestats_result, port_number, + UINT8); +cmdline_parse_token_string_t cmd_pipestats_subport_string = + TOKEN_STRING_INITIALIZER(struct cmd_pipestats_result, subport_string, + "subport"); +cmdline_parse_token_num_t cmd_pipestats_subport_number = + TOKEN_NUM_INITIALIZER(struct cmd_pipestats_result, subport_number, + UINT32); +cmdline_parse_token_string_t cmd_pipestats_pipe_string = + TOKEN_STRING_INITIALIZER(struct cmd_pipestats_result, pipe_string, + "pipe"); +cmdline_parse_token_num_t cmd_pipestats_pipe_number = + TOKEN_NUM_INITIALIZER(struct cmd_pipestats_result, pipe_number, + UINT32); + +cmdline_parse_inst_t cmd_pipestats = { + .f = cmd_pipestats_parsed, + .data = NULL, + .help_str = "Show pipe stats.", + .tokens = { + (void *)&cmd_pipestats_stats_string, + (void *)&cmd_pipestats_port_string, + (void *)&cmd_pipestats_port_number, + (void *)&cmd_pipestats_subport_string, + (void *)&cmd_pipestats_subport_number, + (void *)&cmd_pipestats_pipe_string, + (void *)&cmd_pipestats_pipe_number, + NULL, + }, +}; + +/* *** SHOW AVERAGE QUEUE SIZE (QUEUE) *** */ +struct cmd_avg_q_result { + cmdline_fixed_string_t qavg_string; + cmdline_fixed_string_t port_string; + uint8_t port_number; + cmdline_fixed_string_t subport_string; + uint32_t subport_number; + cmdline_fixed_string_t pipe_string; + uint32_t pipe_number; + cmdline_fixed_string_t tc_string; + uint8_t tc_number; + cmdline_fixed_string_t q_string; + uint8_t q_number; +}; + +static void cmd_avg_q_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_avg_q_result *res = parsed_result; + + if (qavg_q(res->port_number, res->subport_number, res->pipe_number, res->tc_number, res->q_number) < 0) + printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); +} + +cmdline_parse_token_string_t cmd_avg_q_qavg_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, qavg_string, + "qavg"); +cmdline_parse_token_string_t cmd_avg_q_port_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, port_string, + "port"); +cmdline_parse_token_num_t cmd_avg_q_port_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_q_result, port_number, + UINT8); +cmdline_parse_token_string_t cmd_avg_q_subport_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, subport_string, + "subport"); +cmdline_parse_token_num_t cmd_avg_q_subport_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_q_result, subport_number, + UINT32); +cmdline_parse_token_string_t cmd_avg_q_pipe_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, pipe_string, + "pipe"); +cmdline_parse_token_num_t cmd_avg_q_pipe_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_q_result, pipe_number, + UINT32); +cmdline_parse_token_string_t cmd_avg_q_tc_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, tc_string, + "tc"); +cmdline_parse_token_num_t cmd_avg_q_tc_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_q_result, tc_number, + UINT8); +cmdline_parse_token_string_t cmd_avg_q_q_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, q_string, + "q"); +cmdline_parse_token_num_t cmd_avg_q_q_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_q_result, q_number, + UINT8); + +cmdline_parse_inst_t cmd_avg_q = { + .f = cmd_avg_q_parsed, + .data = NULL, + .help_str = "Show pipe stats.", + .tokens = { + (void *)&cmd_avg_q_qavg_string, + (void *)&cmd_avg_q_port_string, + (void *)&cmd_avg_q_port_number, + (void *)&cmd_avg_q_subport_string, + (void *)&cmd_avg_q_subport_number, + (void *)&cmd_avg_q_pipe_string, + (void *)&cmd_avg_q_pipe_number, + (void *)&cmd_avg_q_tc_string, + (void *)&cmd_avg_q_tc_number, + (void *)&cmd_avg_q_q_string, + (void *)&cmd_avg_q_q_number, + NULL, + }, +}; + +/* *** SHOW AVERAGE QUEUE SIZE (tc/pipe) *** */ +struct cmd_avg_tcpipe_result { + cmdline_fixed_string_t qavg_string; + cmdline_fixed_string_t port_string; + uint8_t port_number; + cmdline_fixed_string_t subport_string; + uint32_t subport_number; + cmdline_fixed_string_t pipe_string; + uint32_t pipe_number; + cmdline_fixed_string_t tc_string; + uint8_t tc_number; +}; + +static void cmd_avg_tcpipe_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_avg_tcpipe_result *res = parsed_result; + + if (qavg_tcpipe(res->port_number, res->subport_number, res->pipe_number, res->tc_number) < 0) + printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); +} + +cmdline_parse_token_string_t cmd_avg_tcpipe_qavg_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_tcpipe_result, qavg_string, + "qavg"); +cmdline_parse_token_string_t cmd_avg_tcpipe_port_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_tcpipe_result, port_string, + "port"); +cmdline_parse_token_num_t cmd_avg_tcpipe_port_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_tcpipe_result, port_number, + UINT8); +cmdline_parse_token_string_t cmd_avg_tcpipe_subport_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_tcpipe_result, subport_string, + "subport"); +cmdline_parse_token_num_t cmd_avg_tcpipe_subport_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_tcpipe_result, subport_number, + UINT32); +cmdline_parse_token_string_t cmd_avg_tcpipe_pipe_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_tcpipe_result, pipe_string, + "pipe"); +cmdline_parse_token_num_t cmd_avg_tcpipe_pipe_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_tcpipe_result, pipe_number, + UINT32); +cmdline_parse_token_string_t cmd_avg_tcpipe_tc_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_tcpipe_result, tc_string, + "tc"); +cmdline_parse_token_num_t cmd_avg_tcpipe_tc_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_tcpipe_result, tc_number, + UINT8); + +cmdline_parse_inst_t cmd_avg_tcpipe = { + .f = cmd_avg_tcpipe_parsed, + .data = NULL, + .help_str = "Show pipe stats.", + .tokens = { + (void *)&cmd_avg_tcpipe_qavg_string, + (void *)&cmd_avg_tcpipe_port_string, + (void *)&cmd_avg_tcpipe_port_number, + (void *)&cmd_avg_tcpipe_subport_string, + (void *)&cmd_avg_tcpipe_subport_number, + (void *)&cmd_avg_tcpipe_pipe_string, + (void *)&cmd_avg_tcpipe_pipe_number, + (void *)&cmd_avg_tcpipe_tc_string, + (void *)&cmd_avg_tcpipe_tc_number, + NULL, + }, +}; + +/* *** SHOW AVERAGE QUEUE SIZE (pipe) *** */ +struct cmd_avg_pipe_result { + cmdline_fixed_string_t qavg_string; + cmdline_fixed_string_t port_string; + uint8_t port_number; + cmdline_fixed_string_t subport_string; + uint32_t subport_number; + cmdline_fixed_string_t pipe_string; + uint32_t pipe_number; +}; + +static void cmd_avg_pipe_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_avg_pipe_result *res = parsed_result; + + if (qavg_pipe(res->port_number, res->subport_number, res->pipe_number) < 0) + printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); +} + +cmdline_parse_token_string_t cmd_avg_pipe_qavg_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_pipe_result, qavg_string, + "qavg"); +cmdline_parse_token_string_t cmd_avg_pipe_port_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_pipe_result, port_string, + "port"); +cmdline_parse_token_num_t cmd_avg_pipe_port_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_pipe_result, port_number, + UINT8); +cmdline_parse_token_string_t cmd_avg_pipe_subport_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_pipe_result, subport_string, + "subport"); +cmdline_parse_token_num_t cmd_avg_pipe_subport_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_pipe_result, subport_number, + UINT32); +cmdline_parse_token_string_t cmd_avg_pipe_pipe_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_pipe_result, pipe_string, + "pipe"); +cmdline_parse_token_num_t cmd_avg_pipe_pipe_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_pipe_result, pipe_number, + UINT32); + +cmdline_parse_inst_t cmd_avg_pipe = { + .f = cmd_avg_pipe_parsed, + .data = NULL, + .help_str = "Show pipe stats.", + .tokens = { + (void *)&cmd_avg_pipe_qavg_string, + (void *)&cmd_avg_pipe_port_string, + (void *)&cmd_avg_pipe_port_number, + (void *)&cmd_avg_pipe_subport_string, + (void *)&cmd_avg_pipe_subport_number, + (void *)&cmd_avg_pipe_pipe_string, + (void *)&cmd_avg_pipe_pipe_number, + NULL, + }, +}; + +/* *** SHOW AVERAGE QUEUE SIZE (tc/subport) *** */ +struct cmd_avg_tcsubport_result { + cmdline_fixed_string_t qavg_string; + cmdline_fixed_string_t port_string; + uint8_t port_number; + cmdline_fixed_string_t subport_string; + uint32_t subport_number; + cmdline_fixed_string_t tc_string; + uint8_t tc_number; +}; + +static void cmd_avg_tcsubport_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_avg_tcsubport_result *res = parsed_result; + + if (qavg_tcsubport(res->port_number, res->subport_number, res->tc_number) < 0) + printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); +} + +cmdline_parse_token_string_t cmd_avg_tcsubport_qavg_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_tcsubport_result, qavg_string, + "qavg"); +cmdline_parse_token_string_t cmd_avg_tcsubport_port_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_tcsubport_result, port_string, + "port"); +cmdline_parse_token_num_t cmd_avg_tcsubport_port_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_tcsubport_result, port_number, + UINT8); +cmdline_parse_token_string_t cmd_avg_tcsubport_subport_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_tcsubport_result, subport_string, + "subport"); +cmdline_parse_token_num_t cmd_avg_tcsubport_subport_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_tcsubport_result, subport_number, + UINT32); +cmdline_parse_token_string_t cmd_avg_tcsubport_tc_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_tcsubport_result, tc_string, + "tc"); +cmdline_parse_token_num_t cmd_avg_tcsubport_tc_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_tcsubport_result, tc_number, + UINT8); + +cmdline_parse_inst_t cmd_avg_tcsubport = { + .f = cmd_avg_tcsubport_parsed, + .data = NULL, + .help_str = "Show pipe stats.", + .tokens = { + (void *)&cmd_avg_tcsubport_qavg_string, + (void *)&cmd_avg_tcsubport_port_string, + (void *)&cmd_avg_tcsubport_port_number, + (void *)&cmd_avg_tcsubport_subport_string, + (void *)&cmd_avg_tcsubport_subport_number, + (void *)&cmd_avg_tcsubport_tc_string, + (void *)&cmd_avg_tcsubport_tc_number, + NULL, + }, +}; + +/* *** SHOW AVERAGE QUEUE SIZE (subport) *** */ +struct cmd_avg_subport_result { + cmdline_fixed_string_t qavg_string; + cmdline_fixed_string_t port_string; + uint8_t port_number; + cmdline_fixed_string_t subport_string; + uint32_t subport_number; +}; + +static void cmd_avg_subport_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_avg_subport_result *res = parsed_result; + + if (qavg_subport(res->port_number, res->subport_number) < 0) + printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); +} + +cmdline_parse_token_string_t cmd_avg_subport_qavg_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_subport_result, qavg_string, + "qavg"); +cmdline_parse_token_string_t cmd_avg_subport_port_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_subport_result, port_string, + "port"); +cmdline_parse_token_num_t cmd_avg_subport_port_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_subport_result, port_number, + UINT8); +cmdline_parse_token_string_t cmd_avg_subport_subport_string = + TOKEN_STRING_INITIALIZER(struct cmd_avg_subport_result, subport_string, + "subport"); +cmdline_parse_token_num_t cmd_avg_subport_subport_number = + TOKEN_NUM_INITIALIZER(struct cmd_avg_subport_result, subport_number, + UINT32); + +cmdline_parse_inst_t cmd_avg_subport = { + .f = cmd_avg_subport_parsed, + .data = NULL, + .help_str = "Show pipe stats.", + .tokens = { + (void *)&cmd_avg_subport_qavg_string, + (void *)&cmd_avg_subport_port_string, + (void *)&cmd_avg_subport_port_number, + (void *)&cmd_avg_subport_subport_string, + (void *)&cmd_avg_subport_subport_number, + NULL, + }, +}; + +/* ******************************************************************************** */ + +/* list of instructions */ +cmdline_parse_ctx_t main_ctx[] = { + (cmdline_parse_inst_t *)&cmd_help, + (cmdline_parse_inst_t *)&cmd_setqavg, + (cmdline_parse_inst_t *)&cmd_appstats, + (cmdline_parse_inst_t *)&cmd_subportstats, + (cmdline_parse_inst_t *)&cmd_pipestats, + (cmdline_parse_inst_t *)&cmd_avg_q, + (cmdline_parse_inst_t *)&cmd_avg_tcpipe, + (cmdline_parse_inst_t *)&cmd_avg_pipe, + (cmdline_parse_inst_t *)&cmd_avg_tcsubport, + (cmdline_parse_inst_t *)&cmd_avg_subport, + (cmdline_parse_inst_t *)&cmd_quit, + NULL, +}; + +/* prompt function, called from main on MASTER lcore */ +void +prompt(void) +{ + struct cmdline *cl; + + cl = cmdline_stdin_new(main_ctx, "qos_sched> "); + if (cl == NULL) { + return; + } + cmdline_interact(cl); + cmdline_stdin_exit(cl); +} diff --git a/examples/qos_sched/init.c b/examples/qos_sched/init.c index ca31a1781b..6ffcc80d01 100755 --- a/examples/qos_sched/init.c +++ b/examples/qos_sched/init.c @@ -356,7 +356,7 @@ int app_init(void) app_init_port(qos_conf[i].rx_port, qos_conf[i].mbuf_pool); app_init_port(qos_conf[i].tx_port, qos_conf[i].mbuf_pool); - qos_conf[i].sched_port = app_init_sched_port(qos_conf[i].rx_port, socket); + qos_conf[i].sched_port = app_init_sched_port(qos_conf[i].tx_port, socket); } RTE_LOG(INFO, APP, "time stamp clock running at %" PRIu64 " Hz\n", diff --git a/examples/qos_sched/main.c b/examples/qos_sched/main.c index b5f279d1b3..516bb05be4 100755 --- a/examples/qos_sched/main.c +++ b/examples/qos_sched/main.c @@ -52,6 +52,9 @@ #define APP_WT_MODE 2 #define APP_TX_MODE 4 +uint8_t interactive = APP_INTERACTIVE_DEFAULT; +uint32_t qavg_period = APP_QAVG_PERIOD; +uint32_t qavg_ntimes = APP_QAVG_NTIMES; /* main processing loop */ static int @@ -167,7 +170,7 @@ app_main_loop(__attribute__((unused))void *dummy) return 0; } -static void +void app_stat(void) { uint32_t i; @@ -215,8 +218,6 @@ app_stat(void) } } - - int MAIN(int argc, char **argv) { @@ -230,16 +231,21 @@ MAIN(int argc, char **argv) if (ret < 0) return -1; - /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(app_main_loop, NULL, SKIP_MASTER); - - /* print statistics every second */ - while(1) { + + if (interactive) { sleep(1); - app_stat(); + prompt(); + } + else { + /* print statistics every second */ + while(1) { + sleep(1); + app_stat(); + } } -} - + return 0; +} diff --git a/examples/qos_sched/main.h b/examples/qos_sched/main.h index 3d25a11850..1f991c7b71 100755 --- a/examples/qos_sched/main.h +++ b/examples/qos_sched/main.h @@ -51,6 +51,8 @@ extern "C" { /* * Configurable number of RX/TX ring descriptors */ +#define APP_INTERACTIVE_DEFAULT 0 + #define APP_RX_DESC_DEFAULT 128 #define APP_TX_DESC_DEFAULT 256 @@ -87,6 +89,9 @@ extern "C" { #define APP_STATS_ADD(stat,val) do {(void) (val);} while (0) #endif +#define APP_QAVG_NTIMES 10 +#define APP_QAVG_PERIOD 100 + struct thread_stat { uint64_t nb_rx; @@ -156,6 +161,9 @@ struct ring_thresh uint8_t wthresh; /**< Ring writeback threshold. */ }; +extern uint8_t interactive; +extern uint32_t qavg_period; +extern uint32_t qavg_ntimes; extern uint32_t nb_pfc; extern const char *cfg_profile; extern int mp_size; @@ -173,11 +181,20 @@ int MAIN(int argc, char **argv); int app_parse_args(int argc, char **argv); int app_init(void); +void prompt(void); void app_rx_thread(struct thread_conf **qconf); void app_tx_thread(struct thread_conf **qconf); void app_worker_thread(struct thread_conf **qconf); void app_mixed_thread(struct thread_conf **qconf); +void app_stat(void); +int subport_stat(uint8_t port_id, uint32_t subport_id); +int pipe_stat(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id); +int qavg_q(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, uint8_t q); +int qavg_tcpipe(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc); +int qavg_pipe(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id); +int qavg_tcsubport(uint8_t port_id, uint32_t subport_id, uint8_t tc); +int qavg_subport(uint8_t port_id, uint32_t subport_id); #ifdef __cplusplus } diff --git a/examples/qos_sched/profile_ov.cfg b/examples/qos_sched/profile_ov.cfg new file mode 100644 index 0000000000..4c59b26352 --- /dev/null +++ b/examples/qos_sched/profile_ov.cfg @@ -0,0 +1,90 @@ +; BSD LICENSE +; +; Copyright(c) 2010-2013 Intel Corporation. All rights reserved. +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +; Port configuration +[port] +frame overhead = 24 +number of subports per port = 1 +number of pipes per subport = 32 +queue sizes = 64 64 64 64 + +; Subport configuration +[subport 0] +tb rate = 8400000 ; Bytes per second +tb size = 100000 ; Bytes + +tc 0 rate = 8400000 ; Bytes per second +tc 1 rate = 8400000 ; Bytes per second +tc 2 rate = 8400000 ; Bytes per second +tc 3 rate = 8400000 ; Bytes per second +tc period = 10 ; Milliseconds + +pipe 0-31 = 0 ; These pipes are configured with pipe profile 0 + +; Pipe configuration +[pipe profile 0] +tb rate = 16800000 ; Bytes per second +tb size = 1000000 ; Bytes + +tc 0 rate = 16800000 ; Bytes per second +tc 1 rate = 16800000 ; Bytes per second +tc 2 rate = 16800000 ; Bytes per second +tc 3 rate = 16800000 ; Bytes per second +tc period = 28 ; Milliseconds + +tc 3 oversubscription weight = 1 + +tc 0 wrr weights = 1 1 1 1 +tc 1 wrr weights = 1 1 1 1 +tc 2 wrr weights = 1 1 1 1 +tc 3 wrr weights = 1 1 1 1 + +; RED params per traffic class and color (Green / Yellow / Red) +[red] +tc 0 wred min = 48 40 32 +tc 0 wred max = 64 64 64 +tc 0 wred inv prob = 10 10 10 +tc 0 wred weight = 9 9 9 + +tc 1 wred min = 48 40 32 +tc 1 wred max = 64 64 64 +tc 1 wred inv prob = 10 10 10 +tc 1 wred weight = 9 9 9 + +tc 2 wred min = 48 40 32 +tc 2 wred max = 64 64 64 +tc 2 wred inv prob = 10 10 10 +tc 2 wred weight = 9 9 9 + +tc 3 wred min = 48 40 32 +tc 3 wred max = 64 64 64 +tc 3 wred inv prob = 10 10 10 +tc 3 wred weight = 9 9 9 diff --git a/examples/qos_sched/stats.c b/examples/qos_sched/stats.c new file mode 100644 index 0000000000..4797d66761 --- /dev/null +++ b/examples/qos_sched/stats.c @@ -0,0 +1,316 @@ +/*- + * * BSD LICENSE + * * + * * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * * All rights reserved. + * * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * + * * * Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * * Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in + * * the documentation and/or other materials provided with the + * * distribution. + * * * Neither the name of Intel Corporation nor the names of its + * * contributors may be used to endorse or promote products derived + * * from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * */ + +#include +#include + +#include "main.h" + +int +qavg_q(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, uint8_t q) +{ + struct rte_sched_queue_stats stats; + struct rte_sched_port *port; + uint16_t qlen; + uint32_t queue_id, count, i; + uint32_t average; + + for (i = 0; i < nb_pfc; i++) { + if (qos_conf[i].tx_port == port_id) + break; + } + if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || pipe_id >= port_params.n_pipes_per_subport + || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE || q >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS) + return -1; + + port = qos_conf[i].sched_port; + + queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + pipe_id); + queue_id = queue_id + (tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + q); + + average = 0; + + for (count = 0; count < qavg_ntimes; count++) { + rte_sched_queue_read_stats(port, queue_id, &stats, &qlen); + average += qlen; + usleep(qavg_period); + } + + average /= qavg_ntimes; + + printf("\nAverage queue size: %" PRIu32 " bytes.\n\n", average); + + return 0; +} + +int +qavg_tcpipe(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc) +{ + struct rte_sched_queue_stats stats; + struct rte_sched_port *port; + uint16_t qlen; + uint32_t queue_id, count, i; + uint32_t average, part_average; + + for (i = 0; i < nb_pfc; i++) { + if (qos_conf[i].tx_port == port_id) + break; + } + if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || pipe_id >= port_params.n_pipes_per_subport + || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) + return -1; + + port = qos_conf[i].sched_port; + + queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + pipe_id); + + average = 0; + + for (count = 0; count < qavg_ntimes; count++) { + part_average = 0; + for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { + rte_sched_queue_read_stats(port, queue_id + (tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + i), &stats, &qlen); + part_average += qlen; + } + average += part_average / RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; + usleep(qavg_period); + } + + average /= qavg_ntimes; + + printf("\nAverage queue size: %" PRIu32 " bytes.\n\n", average); + + return 0; +} + +int +qavg_pipe(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id) +{ + struct rte_sched_queue_stats stats; + struct rte_sched_port *port; + uint16_t qlen; + uint32_t queue_id, count, i; + uint32_t average, part_average; + + for (i = 0; i < nb_pfc; i++) { + if (qos_conf[i].tx_port == port_id) + break; + } + if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || pipe_id >= port_params.n_pipes_per_subport) + return -1; + + port = qos_conf[i].sched_port; + + queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + pipe_id); + + average = 0; + + for (count = 0; count < qavg_ntimes; count++) { + part_average = 0; + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { + rte_sched_queue_read_stats(port, queue_id + i, &stats, &qlen); + part_average += qlen; + } + average += part_average / (RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS); + usleep(qavg_period); + } + + average /= qavg_ntimes; + + printf("\nAverage queue size: %" PRIu32 " bytes.\n\n", average); + + return 0; +} + +int +qavg_tcsubport(uint8_t port_id, uint32_t subport_id, uint8_t tc) +{ + struct rte_sched_queue_stats stats; + struct rte_sched_port *port; + uint16_t qlen; + uint32_t queue_id, count, i, j; + uint32_t average, part_average; + + for (i = 0; i < nb_pfc; i++) { + if (qos_conf[i].tx_port == port_id) + break; + } + if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) + return -1; + + port = qos_conf[i].sched_port; + + average = 0; + + for (count = 0; count < qavg_ntimes; count++) { + part_average = 0; + for (i = 0; i < port_params.n_pipes_per_subport; i++) { + queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + i); + + for (j = 0; j < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; j++) { + rte_sched_queue_read_stats(port, queue_id + (tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + j), &stats, &qlen); + part_average += qlen; + } + } + + average += part_average / (port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS); + usleep(qavg_period); + } + + average /= qavg_ntimes; + + printf("\nAverage queue size: %" PRIu32 " bytes.\n\n", average); + + return 0; +} + +int +qavg_subport(uint8_t port_id, uint32_t subport_id) +{ + struct rte_sched_queue_stats stats; + struct rte_sched_port *port; + uint16_t qlen; + uint32_t queue_id, count, i, j; + uint32_t average, part_average; + + for (i = 0; i < nb_pfc; i++) { + if (qos_conf[i].tx_port == port_id) + break; + } + if (i == nb_pfc || subport_id >= port_params.n_subports_per_port) + return -1; + + port = qos_conf[i].sched_port; + + average = 0; + + for (count = 0; count < qavg_ntimes; count++) { + part_average = 0; + for (i = 0; i < port_params.n_pipes_per_subport; i++) { + queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + i); + + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; j++) { + rte_sched_queue_read_stats(port, queue_id + j, &stats, &qlen); + part_average += qlen; + } + } + + average += part_average / (port_params.n_pipes_per_subport * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS); + usleep(qavg_period); + } + + average /= qavg_ntimes; + + printf("\nAverage queue size: %" PRIu32 " bytes.\n\n", average); + + return 0; +} + +int +subport_stat(uint8_t port_id, uint32_t subport_id) +{ + struct rte_sched_subport_stats stats; + struct rte_sched_port *port; + uint32_t tc_ov[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint8_t i; + + for (i = 0; i < nb_pfc; i++) { + if (qos_conf[i].tx_port == port_id) + break; + } + if (i == nb_pfc || subport_id >= port_params.n_subports_per_port) + return -1; + + port = qos_conf[i].sched_port; + memset (tc_ov, 0, sizeof(tc_ov)); + + rte_sched_subport_read_stats(port, subport_id, &stats, tc_ov); + + printf("\n"); + printf("+----+-------------+-------------+-------------+-------------+-------------+\n"); + printf("| TC | Pkts OK |Pkts Dropped | Bytes OK |Bytes Dropped| OV Status |\n"); + printf("+----+-------------+-------------+-------------+-------------+-------------+\n"); + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + printf("| %d | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " |\n", i, + stats.n_pkts_tc[i], stats.n_pkts_tc_dropped[i], + stats.n_bytes_tc[i], stats.n_bytes_tc_dropped[i], tc_ov[i]); + printf("+----+-------------+-------------+-------------+-------------+-------------+\n"); + } + printf("\n"); + + return 0; +} + +int +pipe_stat(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id) +{ + struct rte_sched_queue_stats stats; + struct rte_sched_port *port; + uint16_t qlen; + uint8_t i, j; + uint32_t queue_id; + + for (i = 0; i < nb_pfc; i++) { + if (qos_conf[i].tx_port == port_id) + break; + } + if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || pipe_id >= port_params.n_pipes_per_subport) + return -1; + + port = qos_conf[i].sched_port; + + queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + pipe_id); + + printf("\n"); + printf("+----+-------+-------------+-------------+-------------+-------------+-------------+\n"); + printf("| TC | Queue | Pkts OK |Pkts Dropped | Bytes OK |Bytes Dropped| Length |\n"); + printf("+----+-------+-------------+-------------+-------------+-------------+-------------+\n"); + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + for (j = 0; j < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; j++) { + + rte_sched_queue_read_stats(port, queue_id + (i * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + j), &stats, &qlen); + + printf("| %d | %d | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11i |\n", i, j, + stats.n_pkts, stats.n_pkts_dropped, stats.n_bytes, stats.n_bytes_dropped, qlen); + printf("+----+-------+-------------+-------------+-------------+-------------+-------------+\n"); + } + if (i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE - 1) + printf("+----+-------+-------------+-------------+-------------+-------------+-------------+\n"); + } + printf("\n"); + + return 0; +} +