From ed30d9b691b212081df75a0d38d78996bd4350f7 Mon Sep 17 00:00:00 2001 From: Intel Date: Thu, 20 Dec 2012 00:00:00 +0100 Subject: [PATCH 1/1] app/testpmd: add stats per queue Signed-off-by: Intel --- app/test-pmd/cmdline.c | 78 +++++++++++++++++++-- app/test-pmd/config.c | 144 ++++++++++++++++++++++++++++++++++++-- app/test-pmd/parameters.c | 101 ++++++++++++++++++++++++++ app/test-pmd/testpmd.c | 12 ++++ app/test-pmd/testpmd.h | 25 +++++++ 5 files changed, 348 insertions(+), 12 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 942a6e9bb2..6142c15b98 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -100,8 +100,8 @@ static void cmd_help_parsed(__attribute__((unused)) void *parsed_result, cmdline_printf(cl, "Display informations:\n" "---------------------\n" - "- show port info|stats|fdir X|all\n" - " Diplays information or stats on port X, or all\n" + "- show port info|stats|fdir|stat_qmap X|all\n" + " Diplays information or stats or stats queue mapping on port X, or all\n" "- clear port stats X|all\n" " Clear stats for port X, or all\n" "- show config rxtx|cores|fwd\n" @@ -175,6 +175,9 @@ static void cmd_help_parsed(__attribute__((unused)) void *parsed_result, " Set bit field value of a port register\n" "- write regbit port_id reg_off bit_x value\n" " Set bit value of a port register\n" + "- set stat_qmap tx|rx port_id queue_id qmapping\n" + " Set statistics mapping (qmapping 0..15) for tx|rx queue_id on port_id\n" + " e.g., 'set stat_qmap rx 0 2 5' sets rx queue 2 on port 0 to mapping 5\n" "\n"); cmdline_printf(cl, "Control forwarding:\n" @@ -1631,6 +1634,9 @@ static void cmd_showportall_parsed(void *parsed_result, else if (!strcmp(res->what, "fdir")) for (i = 0; i < nb_ports; i++) fdir_get_infos(i); + else if (!strcmp(res->what, "stat_qmap")) + for (i = 0; i < nb_ports; i++) + nic_stats_mapping_display(i); } cmdline_parse_token_string_t cmd_showportall_show = @@ -1640,13 +1646,13 @@ cmdline_parse_token_string_t cmd_showportall_port = TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, port, "port"); cmdline_parse_token_string_t cmd_showportall_what = TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, what, - "info#stats#fdir"); + "info#stats#fdir#stat_qmap"); cmdline_parse_token_string_t cmd_showportall_all = TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, all, "all"); cmdline_parse_inst_t cmd_showportall = { .f = cmd_showportall_parsed, .data = NULL, - .help_str = "show|clear port info|stats|fdir all", + .help_str = "show|clear port info|stats|fdir|stat_qmap all", .tokens = { (void *)&cmd_showportall_show, (void *)&cmd_showportall_port, @@ -1678,6 +1684,8 @@ static void cmd_showport_parsed(void *parsed_result, nic_stats_display(res->portnum); else if (!strcmp(res->what, "fdir")) fdir_get_infos(res->portnum); + else if (!strcmp(res->what, "stat_qmap")) + nic_stats_mapping_display(res->portnum); } cmdline_parse_token_string_t cmd_showport_show = @@ -1687,14 +1695,14 @@ cmdline_parse_token_string_t cmd_showport_port = TOKEN_STRING_INITIALIZER(struct cmd_showport_result, port, "port"); cmdline_parse_token_string_t cmd_showport_what = TOKEN_STRING_INITIALIZER(struct cmd_showport_result, what, - "info#stats#fdir"); + "info#stats#fdir#stat_qmap"); cmdline_parse_token_num_t cmd_showport_portnum = TOKEN_NUM_INITIALIZER(struct cmd_showport_result, portnum, INT32); cmdline_parse_inst_t cmd_showport = { .f = cmd_showport_parsed, .data = NULL, - .help_str = "show|clear port info|stats|fdir X (X = port number)", + .help_str = "show|clear port info|stats|fdir|stat_qmap X (X = port number)", .tokens = { (void *)&cmd_showport_show, (void *)&cmd_showport_port, @@ -2120,6 +2128,63 @@ cmdline_parse_inst_t cmd_mac_addr = { }; +/* *** CONFIGURE QUEUE STATS COUNTER MAPPINGS *** */ +struct cmd_set_qmap_result { + cmdline_fixed_string_t set; + cmdline_fixed_string_t qmap; + cmdline_fixed_string_t what; + uint8_t port_id; + uint16_t queue_id; + uint8_t map_value; +}; + +static void +cmd_set_qmap_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_set_qmap_result *res = parsed_result; + int is_rx = (strcmp(res->what, "tx") == 0) ? 0 : 1; + + set_qmap(res->port_id, (uint8_t)is_rx, res->queue_id, res->map_value); +} + +cmdline_parse_token_string_t cmd_setqmap_set = + TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result, + set, "set"); +cmdline_parse_token_string_t cmd_setqmap_qmap = + TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result, + qmap, "stat_qmap"); +cmdline_parse_token_string_t cmd_setqmap_what = + TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result, + what, "tx#rx"); +cmdline_parse_token_num_t cmd_setqmap_portid = + TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result, + port_id, UINT8); +cmdline_parse_token_num_t cmd_setqmap_queueid = + TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result, + queue_id, UINT16); +cmdline_parse_token_num_t cmd_setqmap_mapvalue = + TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result, + map_value, UINT8); + +cmdline_parse_inst_t cmd_set_qmap = { + .f = cmd_set_qmap_parsed, + .data = NULL, + .help_str = "Set statistics mapping value on tx|rx queue_id of port_id", + .tokens = { + (void *)&cmd_setqmap_set, + (void *)&cmd_setqmap_qmap, + (void *)&cmd_setqmap_what, + (void *)&cmd_setqmap_portid, + (void *)&cmd_setqmap_queueid, + (void *)&cmd_setqmap_mapvalue, + NULL, + }, +}; + +/* ******************************************************************************** */ + /* list of instructions */ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help, @@ -2161,6 +2226,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_masks_filter, (cmdline_parse_inst_t *)&cmd_stop, (cmdline_parse_inst_t *)&cmd_mac_addr, + (cmdline_parse_inst_t *)&cmd_set_qmap, NULL, }; diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index e5bce93a30..bbf837d536 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -83,6 +83,8 @@ void nic_stats_display(portid_t port_id) { struct rte_eth_stats stats; + struct rte_port *port = &ports[port_id]; + uint8_t i; static const char *nic_stats_border = "########################"; @@ -93,12 +95,23 @@ nic_stats_display(portid_t port_id) rte_eth_stats_get(port_id, &stats); printf("\n %s NIC statistics for port %-2d %s\n", nic_stats_border, port_id, nic_stats_border); - printf(" RX-packets: %-10"PRIu64" RX-errors: %-10"PRIu64"RX-bytes: " - "%-"PRIu64"\n" - " TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64"TX-bytes: " - "%-"PRIu64"\n", - stats.ipackets, stats.ierrors, stats.ibytes, - stats.opackets, stats.oerrors, stats.obytes); + + if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) { + printf(" RX-packets: %-10"PRIu64" RX-errors: %-10"PRIu64"RX-bytes: " + "%-"PRIu64"\n" + " TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64"TX-bytes: " + "%-"PRIu64"\n", + stats.ipackets, stats.ierrors, stats.ibytes, + stats.opackets, stats.oerrors, stats.obytes); + } + else { + printf(" RX-packets: %10"PRIu64" RX-errors: %10"PRIu64 + " RX-bytes: %10"PRIu64"\n" + " TX-packets: %10"PRIu64" TX-errors: %10"PRIu64 + " TX-bytes: %10"PRIu64"\n", + stats.ipackets, stats.ierrors, stats.ibytes, + stats.opackets, stats.oerrors, stats.obytes); + } /* stats fdir */ if (fdir_conf.mode != RTE_FDIR_MODE_NONE) @@ -106,6 +119,24 @@ nic_stats_display(portid_t port_id) stats.fdirmiss, stats.fdirmatch); + if (port->rx_queue_stats_mapping_enabled) { + printf("\n"); + for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { + printf(" Stats reg %2d RX-packets: %10"PRIu64 + " RX-errors: %10"PRIu64 + " RX-bytes: %10"PRIu64"\n", + i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]); + } + } + if (port->tx_queue_stats_mapping_enabled) { + printf("\n"); + for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { + printf(" Stats reg %2d TX-packets: %10"PRIu64 + " TX-bytes: %10"PRIu64"\n", + i, stats.q_opackets[i], stats.q_obytes[i]); + } + } + printf(" %s############################%s\n", nic_stats_border, nic_stats_border); } @@ -121,6 +152,55 @@ nic_stats_clear(portid_t port_id) printf("\n NIC statistics for port %d cleared\n", port_id); } + +void +nic_stats_mapping_display(portid_t port_id) +{ + struct rte_port *port = &ports[port_id]; + uint16_t i; + + static const char *nic_stats_mapping_border = "########################"; + + if (port_id >= nb_ports) { + printf("Invalid port, range is [0, %d]\n", nb_ports - 1); + return; + } + + if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) { + printf("Port id %d - either does not support queue statistic mapping or" + " no queue statistic mapping set\n", port_id); + return; + } + + printf("\n %s NIC statistics mapping for port %-2d %s\n", + nic_stats_mapping_border, port_id, nic_stats_mapping_border); + + if (port->rx_queue_stats_mapping_enabled) { + for (i = 0; i < nb_rx_queue_stats_mappings; i++) { + if (rx_queue_stats_mappings[i].port_id == port_id) { + printf(" RX-queue %2d mapped to Stats Reg %2d\n", + rx_queue_stats_mappings[i].queue_id, + rx_queue_stats_mappings[i].stats_counter_id); + } + } + printf("\n"); + } + + + if (port->tx_queue_stats_mapping_enabled) { + for (i = 0; i < nb_tx_queue_stats_mappings; i++) { + if (tx_queue_stats_mappings[i].port_id == port_id) { + printf(" TX-queue %2d mapped to Stats Reg %2d\n", + tx_queue_stats_mappings[i].queue_id, + tx_queue_stats_mappings[i].stats_counter_id); + } + } + } + + printf(" %s####################################%s\n", + nic_stats_mapping_border, nic_stats_mapping_border); +} + void port_infos_display(portid_t port_id) { @@ -978,6 +1058,58 @@ tx_vlan_reset(portid_t port_id) ports[port_id].tx_ol_flags &= ~PKT_TX_VLAN_PKT; } +void +set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value) +{ + uint16_t i; + uint8_t existing_mapping_found = 0; + + if (port_id_is_invalid(port_id)) + return; + + if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id))) + return; + + if (map_value >= RTE_ETHDEV_QUEUE_STAT_CNTRS) { + printf("map_value not in required range 0..%d\n", + RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); + return; + } + + if (!is_rx) { /*then tx*/ + for (i = 0; i < nb_tx_queue_stats_mappings; i++) { + if ((tx_queue_stats_mappings[i].port_id == port_id) && + (tx_queue_stats_mappings[i].queue_id == queue_id)) { + tx_queue_stats_mappings[i].stats_counter_id = map_value; + existing_mapping_found = 1; + break; + } + } + if (!existing_mapping_found) { /* A new additional mapping... */ + tx_queue_stats_mappings[nb_tx_queue_stats_mappings].port_id = port_id; + tx_queue_stats_mappings[nb_tx_queue_stats_mappings].queue_id = queue_id; + tx_queue_stats_mappings[nb_tx_queue_stats_mappings].stats_counter_id = map_value; + nb_tx_queue_stats_mappings++; + } + } + else { /*rx*/ + for (i = 0; i < nb_rx_queue_stats_mappings; i++) { + if ((rx_queue_stats_mappings[i].port_id == port_id) && + (rx_queue_stats_mappings[i].queue_id == queue_id)) { + rx_queue_stats_mappings[i].stats_counter_id = map_value; + existing_mapping_found = 1; + break; + } + } + if (!existing_mapping_found) { /* A new additional mapping... */ + rx_queue_stats_mappings[nb_rx_queue_stats_mappings].port_id = port_id; + rx_queue_stats_mappings[nb_rx_queue_stats_mappings].queue_id = queue_id; + rx_queue_stats_mappings[nb_rx_queue_stats_mappings].stats_counter_id = map_value; + nb_rx_queue_stats_mappings++; + } + } +} + void tx_cksum_set(portid_t port_id, uint8_t cksum_mask) { diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index 8d14879234..526202a3f4 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -155,6 +155,12 @@ usage(char* progname) " (0 <= N <= value of txd)\n"); printf(" --txrst=N set the transmit RS bit threshold of TX rings to N" " (0 <= N <= value of txd)\n"); + printf(" --tx-queue-stats-mapping (port,queue,mapping)[,(port,queue,mapping]:" + " tx queues statistics counters mapping" + " (0 <= mapping <= %d)\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); + printf(" --rx-queue-stats-mapping (port,queue,mapping)[,(port,queue,mapping]:" + " rx queues statistics counters mapping" + " (0 <= mapping <= %d)\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); } static int @@ -224,6 +230,87 @@ parse_fwd_portmask(const char *portmask) set_fwd_ports_mask((uint64_t) pm); } + +static int +parse_queue_stats_mapping_config(const char *q_arg, int is_rx) +{ + char s[256]; + const char *p, *p0 = q_arg; + char *end; + enum fieldnames { + FLD_PORT = 0, + FLD_QUEUE, + FLD_STATS_COUNTER, + _NUM_FLD + }; + unsigned long int_fld[_NUM_FLD]; + char *str_fld[_NUM_FLD]; + int i; + unsigned size; + + /* reset from value set at definition */ + is_rx ? (nb_rx_queue_stats_mappings = 0) : (nb_tx_queue_stats_mappings = 0); + + while ((p = strchr(p0,'(')) != NULL) { + ++p; + if((p0 = strchr(p,')')) == NULL) + return -1; + + size = p0 - p; + if(size >= sizeof(s)) + return -1; + + rte_snprintf(s, sizeof(s), "%.*s", size, p); + if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) + return -1; + for (i = 0; i < _NUM_FLD; i++){ + errno = 0; + int_fld[i] = strtoul(str_fld[i], &end, 0); + if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) + return -1; + } + /* Check mapping field is in correct range (0..RTE_ETHDEV_QUEUE_STAT_CNTRS-1) */ + if (int_fld[FLD_STATS_COUNTER] >= RTE_ETHDEV_QUEUE_STAT_CNTRS) { + printf("Stats counter not in the correct range 0..%d\n", + RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); + return -1; + } + + if (is_rx ? (nb_rx_queue_stats_mappings >= MAX_RX_QUEUE_STATS_MAPPINGS) : + (nb_tx_queue_stats_mappings >= MAX_TX_QUEUE_STATS_MAPPINGS)) { + printf("exceeded max number of %s queue statistics mappings: %hu\n", + is_rx ? "RX" : "TX", + is_rx ? nb_rx_queue_stats_mappings : nb_tx_queue_stats_mappings); + return -1; + } + if (!is_rx) { + tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].port_id = + (uint8_t)int_fld[FLD_PORT]; + tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].queue_id = + (uint8_t)int_fld[FLD_QUEUE]; + tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].stats_counter_id = + (uint8_t)int_fld[FLD_STATS_COUNTER]; + ++nb_tx_queue_stats_mappings; + } + else { + rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].port_id = + (uint8_t)int_fld[FLD_PORT]; + rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].queue_id = + (uint8_t)int_fld[FLD_QUEUE]; + rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].stats_counter_id = + (uint8_t)int_fld[FLD_STATS_COUNTER]; + ++nb_rx_queue_stats_mappings; + } + + } +/* Reassign the rx/tx_queue_stats_mappings pointer to point to this newly populated array rather */ +/* than to the default array (that was set at its definition) */ + is_rx ? (rx_queue_stats_mappings = rx_queue_stats_mappings_array) : + (tx_queue_stats_mappings = tx_queue_stats_mappings_array); + return 0; +} + + void launch_args_parse(int argc, char** argv) { @@ -269,6 +356,8 @@ launch_args_parse(int argc, char** argv) { "rxht", 1, 0, 0 }, { "rxwt", 1, 0, 0 }, { "rxfreet", 1, 0, 0 }, + { "tx-queue-stats-mapping", 1, 0, 0 }, + { "rx-queue-stats-mapping", 1, 0, 0 }, { 0, 0, 0, 0 }, }; @@ -630,6 +719,18 @@ launch_args_parse(int argc, char** argv) else rte_exit(EXIT_FAILURE, "rxfreet must be >= 0\n"); } + if (!strcmp(lgopts[opt_idx].name, "tx-queue-stats-mapping")) { + if (parse_queue_stats_mapping_config(optarg, TX)) { + rte_exit(EXIT_FAILURE, + "invalid TX queue statistics mapping config entered\n"); + } + } + if (!strcmp(lgopts[opt_idx].name, "rx-queue-stats-mapping")) { + if (parse_queue_stats_mapping_config(optarg, RX)) { + rte_exit(EXIT_FAILURE, + "invalid RX queue statistics mapping config entered\n"); + } + } break; case 'h': usage(argv[0]); diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 6963598f19..44614fb3ca 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -245,6 +245,18 @@ struct rte_fdir_conf fdir_conf = { static volatile int test_done = 1; /* stop packet forwarding when set to 1. */ +struct queue_stats_mappings tx_queue_stats_mappings_array[MAX_TX_QUEUE_STATS_MAPPINGS]; +struct queue_stats_mappings rx_queue_stats_mappings_array[MAX_RX_QUEUE_STATS_MAPPINGS]; + +struct queue_stats_mappings *tx_queue_stats_mappings = tx_queue_stats_mappings_array; +struct queue_stats_mappings *rx_queue_stats_mappings = rx_queue_stats_mappings_array; + +uint16_t nb_tx_queue_stats_mappings = 0; +uint16_t nb_rx_queue_stats_mappings = 0; + +/* Forward function declarations */ +static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); + /* * Setup default configuration. */ diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 2fa43c3c56..6a5a6d44be 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -131,6 +131,8 @@ struct rte_port { void *fwd_ctx; /**< Forwarding mode context */ uint64_t rx_bad_ip_csum; /**< rx pkts with bad ip checksum */ uint64_t rx_bad_l4_csum; /**< rx pkts with bad l4 checksum */ + uint8_t tx_queue_stats_mapping_enabled; + uint8_t rx_queue_stats_mapping_enabled; }; /** @@ -197,6 +199,25 @@ struct fwd_config { portid_t nb_fwd_ports; /**< Nb. of ports involved. */ }; +#define MAX_TX_QUEUE_STATS_MAPPINGS 1024 /* MAX_PORT of 32 @ 32 tx_queues/port */ +#define MAX_RX_QUEUE_STATS_MAPPINGS 4096 /* MAX_PORT of 32 @ 128 rx_queues/port */ + +struct queue_stats_mappings { + uint8_t port_id; + uint16_t queue_id; + uint8_t stats_counter_id; +} __rte_cache_aligned; + +extern struct queue_stats_mappings tx_queue_stats_mappings_array[]; +extern struct queue_stats_mappings rx_queue_stats_mappings_array[]; + +/* Assign both tx and rx queue stats mappings to the same default values */ +extern struct queue_stats_mappings *tx_queue_stats_mappings; +extern struct queue_stats_mappings *rx_queue_stats_mappings; + +extern uint16_t nb_tx_queue_stats_mappings; +extern uint16_t nb_rx_queue_stats_mappings; + /* globals used for configuration */ extern uint16_t verbose_level; /**< Drives messages being displayed, if any. */ extern uint8_t interactive; @@ -330,6 +351,7 @@ void launch_args_parse(int argc, char** argv); void prompt(void); void nic_stats_display(portid_t port_id); void nic_stats_clear(portid_t port_id); +void nic_stats_mapping_display(portid_t port_id); void port_infos_display(portid_t port_id); void fwd_lcores_config_display(void); void fwd_config_display(void); @@ -363,6 +385,9 @@ void rx_vlan_all_filter_set(portid_t port_id, int on); void tx_vlan_set(portid_t port_id, uint16_t vlan_id); void tx_vlan_reset(portid_t port_id); + +void set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value); + void tx_cksum_set(portid_t port_id, uint8_t cksum_mask); void set_verbose_level(uint16_t vb_level); -- 2.20.1