From 2cd03b79c4415b5b300bc9f3dde7057e2d31b2a2 Mon Sep 17 00:00:00 2001 From: Xavier Simonart Date: Mon, 30 Dec 2019 23:49:52 +0100 Subject: Added command lat all stats lat all stats combines "lat stats" and "lat packets" within one command. This command returns: - One line in case the core_task parser fails. In that case the line will start with: "error: invalid syntax" - One set of lines for each core task: - if core/task is invalid, or not running lat mode, the line will contain (start with) "error...". this will be the only line for that core/task. - Otherwise the set of lines will be: - One line as returned by "lat stats". This line will be - One line starting with "error" in case of error, or - One line containing lat_min_usec, lat_max_usec, lat_avg_usec, tot_lat_min_usec, tot_lat_max_usec, last_tsc, rte_get_tsc_hz(), lcore_id, task_id - The return from lat packets i.e. - One line starting with "error" in case of error, or - 128 lines - one for each bucket - as returned by "lat packets" command This command is more useful then lat packets, as it contains the tsc - needed to see whether the sample is new or not. Change-Id: I04231aa7c5bd2d352ed6f94d40e88d3b411ce744 Signed-off-by: Xavier Simonart --- VNFs/DPPD-PROX/cmd_parser.c | 307 +++++++++++++++++---------------- VNFs/DPPD-PROX/display_latency_distr.c | 5 +- VNFs/DPPD-PROX/handle_lat.h | 3 + 3 files changed, 161 insertions(+), 154 deletions(-) diff --git a/VNFs/DPPD-PROX/cmd_parser.c b/VNFs/DPPD-PROX/cmd_parser.c index 3e71c569..0dd173f3 100644 --- a/VNFs/DPPD-PROX/cmd_parser.c +++ b/VNFs/DPPD-PROX/cmd_parser.c @@ -1693,11 +1693,15 @@ static int parse_cmd_core_stats(const char *str, struct input *input) return 0; } -static int parse_cmd_dp_core_stats(const char *str, struct input *input) +typedef void (*parser_handler)(unsigned, unsigned, struct input *); +static int handle_cores_tasks(const char *str, struct input *input, const char *mode_str, const char *mode_name, parser_handler f) { - unsigned lcores[RTE_MAX_LCORE], tasks[MAX_TASKS_PER_CORE], lcore_id, task_id, nb_cores, nb_tasks; - // This function either outputs a single line, in case of syntax error on the lists of cores and/or tasks + // or outputs (nb_cores * nb_tasks) lines, one line for each core/task pair: + // - if the core/task pair is invalid, the output line reports an error + // - otherwise, the output line provides the latency statistics for the core/task pair + + unsigned lcores[RTE_MAX_LCORE], tasks[MAX_TASKS_PER_CORE], lcore_id, task_id, nb_cores, nb_tasks; if (parse_cores_tasks(str, lcores, tasks, &nb_cores, &nb_tasks)) { if (input->reply) { char buf[128]; @@ -1707,9 +1711,6 @@ static int parse_cmd_dp_core_stats(const char *str, struct input *input) return -1; } - // or outputs (nb_cores * nb_tasks) lines, one line for each core/task pair: - // - if the core/task pair is invalid, the output line reports an error - // - otherwise, the output line provides the dataplane statistics for the core/task pair for (unsigned int i = 0; i < nb_cores; i++) { for (unsigned int j = 0; j < nb_tasks; j++) { lcore_id = lcores[i]; @@ -1724,122 +1725,174 @@ static int parse_cmd_dp_core_stats(const char *str, struct input *input) } continue; } - uint64_t tot_rx = stats_core_task_tot_rx(lcore_id, task_id); - uint64_t tot_tx = stats_core_task_tot_tx(lcore_id, task_id); - uint64_t tot_tx_fail = stats_core_task_tot_tx_fail(lcore_id, task_id); - uint64_t tot_rx_non_dp = stats_core_task_tot_rx_non_dp(lcore_id, task_id); - uint64_t tot_tx_non_dp = stats_core_task_tot_tx_non_dp(lcore_id, task_id); - uint64_t tot_drop = stats_core_task_tot_drop(lcore_id, task_id); - uint64_t last_tsc = stats_core_task_last_tsc(lcore_id, task_id); - - if (input->reply) { - char buf[128]; - snprintf(buf, sizeof(buf), - "%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%u,%u\n", - tot_rx, tot_tx, tot_rx_non_dp, tot_tx_non_dp, tot_drop, tot_tx_fail, last_tsc, rte_get_tsc_hz(), lcore_id, task_id); - input->reply(input, buf, strlen(buf)); - } - else { - plog_info("core: %u, task: %u, RX: %"PRIu64", TX: %"PRIu64", RX_NON_DP: %"PRIu64", TX_NON_DP: %"PRIu64", DROP: %"PRIu64", TX_FAIL: %"PRIu64"\n", - lcore_id, task_id, tot_rx, tot_tx, tot_rx_non_dp, tot_tx_non_dp, tot_drop, tot_tx_fail); + if ((mode_str) && (!task_is_mode(lcore_id, task_id, mode_str))) { + if (input->reply) { + char buf[128]; + snprintf(buf, sizeof(buf), "error: core %u task %u is not measuring %s\n", lcore_id, task_id, mode_name); + input->reply(input, buf, strlen(buf)); + } else { + plog_info("error: core %u task %u is not measuring %s\n", lcore_id, task_id, mode_name); + } + continue; } + f(lcore_id, task_id, input); } } return 0; } -static int parse_cmd_lat_stats(const char *str, struct input *input) +static void handle_dp_core_stats(unsigned lcore_id, unsigned task_id, struct input *input) { - unsigned lcores[RTE_MAX_LCORE], tasks[MAX_TASKS_PER_CORE], lcore_id, task_id, nb_cores, nb_tasks; + uint64_t tot_rx = stats_core_task_tot_rx(lcore_id, task_id); + uint64_t tot_tx = stats_core_task_tot_tx(lcore_id, task_id); + uint64_t tot_tx_fail = stats_core_task_tot_tx_fail(lcore_id, task_id); + uint64_t tot_rx_non_dp = stats_core_task_tot_rx_non_dp(lcore_id, task_id); + uint64_t tot_tx_non_dp = stats_core_task_tot_tx_non_dp(lcore_id, task_id); + uint64_t tot_drop = stats_core_task_tot_drop(lcore_id, task_id); + uint64_t last_tsc = stats_core_task_last_tsc(lcore_id, task_id); - // This function either outputs a single line, in case of syntax error on the lists of cores and/or tasks - if (parse_cores_tasks(str, lcores, tasks, &nb_cores, &nb_tasks)) { + if (input->reply) { + char buf[128]; + snprintf(buf, sizeof(buf), + "%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%u,%u\n", + tot_rx, tot_tx, tot_rx_non_dp, tot_tx_non_dp, tot_drop, tot_tx_fail, last_tsc, rte_get_tsc_hz(), lcore_id, task_id); + input->reply(input, buf, strlen(buf)); + } + else { + plog_info("core: %u, task: %u, RX: %"PRIu64", TX: %"PRIu64", RX_NON_DP: %"PRIu64", TX_NON_DP: %"PRIu64", DROP: %"PRIu64", TX_FAIL: %"PRIu64"\n", + lcore_id, task_id, tot_rx, tot_tx, tot_rx_non_dp, tot_tx_non_dp, tot_drop, tot_tx_fail); + } +} + +static void handle_lat_stats(unsigned lcore_id, unsigned task_id, struct input *input) +{ + struct stats_latency *stats = stats_latency_find(lcore_id, task_id); + struct stats_latency *tot = stats_latency_tot_find(lcore_id, task_id); + if (!stats || !tot) { if (input->reply) { char buf[128]; - snprintf(buf, sizeof(buf), "error: invalid syntax\n"); + snprintf(buf, sizeof(buf), + "error: core %u task %u stats = %p tot = %p\n", + lcore_id, task_id, stats, tot); input->reply(input, buf, strlen(buf)); + } else { + plog_info("error: core %u task %u stats = %p tot = %p\n", + lcore_id, task_id, stats, tot); } - return -1; + return; } - // or outputs (nb_cores * nb_tasks) lines, one line for each core/task pair: - // - if the core/task pair is invalid, the output line reports an error - // - otherwise, the output line provides the latency statistics for the core/task pair - for (unsigned int i = 0; i < nb_cores; i++) { - for (unsigned int j = 0; j < nb_tasks; j++) { - lcore_id = lcores[i]; - task_id = tasks[j]; - if (core_task_is_valid(lcore_id, task_id) == 0) { - if (input->reply) { - char buf[128]; - snprintf(buf, sizeof(buf), "error: invalid core %u, task %u\n", lcore_id, task_id); - input->reply(input, buf, strlen(buf)); - } else { - plog_info("error: invalid core %u, task %u\n", lcore_id, task_id); - } - continue; - } - if (!task_is_mode(lcore_id, task_id, "lat")) { - if (input->reply) { - char buf[128]; - snprintf(buf, sizeof(buf), "error: core %u task %u is not measuring latency\n", lcore_id, task_id); - input->reply(input, buf, strlen(buf)); - } else { - plog_info("error: core %u task %u is not measuring latency\n", lcore_id, task_id); - } - continue; - } + uint64_t last_tsc = stats_core_task_last_tsc(lcore_id, task_id); + uint64_t lat_min_usec = time_unit_to_usec(&stats->min.time); + uint64_t lat_max_usec = time_unit_to_usec(&stats->max.time); + uint64_t tot_lat_min_usec = time_unit_to_usec(&tot->min.time); + uint64_t tot_lat_max_usec = time_unit_to_usec(&tot->max.time); + uint64_t lat_avg_usec = time_unit_to_usec(&stats->avg.time); - struct stats_latency *stats = stats_latency_find(lcore_id, task_id); - struct stats_latency *tot = stats_latency_tot_find(lcore_id, task_id); - if (!stats || !tot) { - if (input->reply) { - char buf[128]; - snprintf(buf, sizeof(buf), - "error: core %u task %u stats = %p tot = %p\n", - lcore_id, task_id, stats, tot); - input->reply(input, buf, strlen(buf)); - } else { - plog_info("error: core %u task %u stats = %p tot = %p\n", - lcore_id, task_id, stats, tot); - } - continue; - } + if (input->reply) { + char buf[128]; + snprintf(buf, sizeof(buf), + "%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%u,%u\n", + lat_min_usec, + lat_max_usec, + lat_avg_usec, + tot_lat_min_usec, + tot_lat_max_usec, + last_tsc, + rte_get_tsc_hz(), + lcore_id, + task_id); + input->reply(input, buf, strlen(buf)); + } + else { + plog_info("core: %u, task: %u, min: %"PRIu64", max: %"PRIu64", avg: %"PRIu64", min since reset: %"PRIu64", max since reset: %"PRIu64"\n", + lcore_id, + task_id, + lat_min_usec, + lat_max_usec, + lat_avg_usec, + tot_lat_min_usec, + tot_lat_max_usec); + } +} - uint64_t last_tsc = stats_core_task_last_tsc(lcore_id, task_id); - uint64_t lat_min_usec = time_unit_to_usec(&stats->min.time); - uint64_t lat_max_usec = time_unit_to_usec(&stats->max.time); - uint64_t tot_lat_min_usec = time_unit_to_usec(&tot->min.time); - uint64_t tot_lat_max_usec = time_unit_to_usec(&tot->max.time); - uint64_t lat_avg_usec = time_unit_to_usec(&stats->avg.time); +#ifdef LATENCY_HISTOGRAM +static void handle_latency_histogram(unsigned lcore_id, unsigned task_id, struct input *input) +{ + uint64_t *buckets; - if (input->reply) { - char buf[128]; - snprintf(buf, sizeof(buf), - "%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%u,%u\n", - lat_min_usec, - lat_max_usec, - lat_avg_usec, - tot_lat_min_usec, - tot_lat_max_usec, - last_tsc, - rte_get_tsc_hz(), - lcore_id, - task_id); - input->reply(input, buf, strlen(buf)); - } - else { - plog_info("core: %u, task: %u, min: %"PRIu64", max: %"PRIu64", avg: %"PRIu64", min since reset: %"PRIu64", max since reset: %"PRIu64"\n", - lcore_id, - task_id, - lat_min_usec, - lat_max_usec, - lat_avg_usec, - tot_lat_min_usec, - tot_lat_max_usec); - } + stats_core_lat_histogram(lcore_id, task_id, &buckets); + + if (buckets == NULL) { + if (input->reply) { + char buf[128]; + snprintf(buf, sizeof(buf), "error: unexpected NULL bucket\n"); + input->reply(input, buf, strlen(buf)); } + return; + } + + if (input->reply) { + char buf[4096] = {0}; + for (size_t i = 0; i < LAT_BUCKET_COUNT; i++) + sprintf(buf+strlen(buf), "Bucket [%zu]: %"PRIu64"\n", i, buckets[i]); + input->reply(input, buf, strlen(buf)); + } + else { + for (size_t i = 0; i < LAT_BUCKET_COUNT; i++) + if (buckets[i]) + plog_info("Bucket [%zu]: %"PRIu64"\n", i, buckets[i]); + } +} + +static void handle_stats_and_packets(unsigned lcore_id, unsigned task_id, struct input *input) +{ + handle_lat_stats(lcore_id, task_id, input); + handle_latency_histogram(lcore_id, task_id, input); +} +#endif + +static int parse_cmd_dp_core_stats(const char *str, struct input *input) +{ + handle_cores_tasks(str, input, NULL, NULL, handle_dp_core_stats); + return 0; +} + +static int parse_cmd_lat_stats(const char *str, struct input *input) +{ + handle_cores_tasks(str, input, "lat", "latency", handle_lat_stats); + return 0; +} + +static int parse_cmd_lat_packets(const char *str, struct input *input) +{ +#ifdef LATENCY_HISTOGRAM + handle_cores_tasks(str, input, "lat", "latency", handle_latency_histogram); +#else + if (input->reply) { + char buf[128]; + snprintf(buf, sizeof(buf), "error: invalid syntax (LATENCY_HISTOGRAM disabled)\n"); + input->reply(input, buf, strlen(buf)); + } else { + plog_info("LATENCY_HISTOGRAMS disabled\n"); } +#endif + return 0; +} + +static int parse_cmd_lat_stats_and_packets(const char *str, struct input *input) +{ +#ifdef LATENCY_HISTOGRAM + handle_cores_tasks(str, input, "lat", "latency", handle_stats_and_packets); +#else + if (input->reply) { + char buf[128]; + snprintf(buf, sizeof(buf), "error: invalid syntax (LATENCY_HISTOGRAMS disabled)\n"); + input->reply(input, buf, strlen(buf)); + } else { + plog_info("LATENCY_HISTOGRAMS disabled\n"); + } +#endif return 0; } @@ -1888,53 +1941,6 @@ static int parse_cmd_irq(const char *str, struct input *input) return 0; } -static void task_lat_show_latency_histogram(uint8_t lcore_id, uint8_t task_id, struct input *input) -{ -#ifdef LATENCY_HISTOGRAM - uint64_t *buckets; - - stats_core_lat_histogram(lcore_id, task_id, &buckets); - - if (buckets == NULL) - return; - - if (input->reply) { - char buf[4096] = {0}; - for (size_t i = 0; i < 128; i++) - sprintf(buf+strlen(buf), "Bucket [%zu]: %"PRIu64"\n", i, buckets[i]); - input->reply(input, buf, strlen(buf)); - } - else { - for (size_t i = 0; i < 128; i++) - if (buckets[i]) - plog_info("Bucket [%zu]: %"PRIu64"\n", i, buckets[i]); - } -#else - plog_info("LATENCY_HISTOGRAM disabled\n"); -#endif -} - -static int parse_cmd_lat_packets(const char *str, struct input *input) -{ - unsigned lcores[RTE_MAX_LCORE], lcore_id, task_id, nb_cores; - - if (parse_cores_task(str, lcores, &task_id, &nb_cores)) - return -1; - - if (cores_task_are_valid(lcores, task_id, nb_cores)) { - for (unsigned int i = 0; i < nb_cores; i++) { - lcore_id = lcores[i]; - if (!task_is_mode(lcore_id, task_id, "lat")) { - plog_err("Core %u task %u is not measuring latency\n", lcore_id, task_id); - } - else { - task_lat_show_latency_histogram(lcore_id, task_id, input); - } - } - } - return 0; -} - static int parse_cmd_cgnat_public_hash(const char *str, struct input *input) { unsigned lcores[RTE_MAX_LCORE], lcore_id, task_id, nb_cores; @@ -2161,6 +2167,7 @@ static struct cmd_str cmd_strings[] = { {"irq stats", " ", "Print irq related infos", parse_cmd_irq}, {"show irq buckets", " ", "Print irq buckets", parse_cmd_show_irq_buckets}, {"lat packets", " ", "Print the latency for each of the last set of packets", parse_cmd_lat_packets}, + {"lat all stats", " ", "Print the latency for each of the last set of packets as well as latency distribution", parse_cmd_lat_stats_and_packets}, {"accuracy limit", " ", "Only consider latency of packets that were measured with an error no more than ", parse_cmd_accuracy}, {"core stats", " ", "Print rx/tx/drop for task running on core ", parse_cmd_core_stats}, {"dp core stats", " ", "Print rx/tx/non_dp_rx/non_dp_tx/drop for task running on core ", parse_cmd_dp_core_stats}, diff --git a/VNFs/DPPD-PROX/display_latency_distr.c b/VNFs/DPPD-PROX/display_latency_distr.c index 9808a702..3e1cc38a 100644 --- a/VNFs/DPPD-PROX/display_latency_distr.c +++ b/VNFs/DPPD-PROX/display_latency_distr.c @@ -35,7 +35,7 @@ static uint32_t group_size = 9; //LAT_BUCKET_COUNT / global_nb_buckets_displayed static void display_latency_distr_draw_frame(struct screen_state *state) { - uint32_t n_tasks = stats_get_n_latency(); + uint32_t n_tasks = stats_get_n_latency(); struct lcore_cfg *lconf = NULL; struct task_args *targ; char name[32]; @@ -166,9 +166,6 @@ static void display_latency_distr_draw_stats(struct screen_state *state) if (i + j < LAT_BUCKET_COUNT) nb += bucket[i+j]; display_column_print(stats_latency_distr[k++], count, "%9lu", nb); - if ((nb == 16) || (nb == 48)) - for (uint32_t j = 0; j <= group_size; j++) - plog_info("id %d: %ld\n", i+j, bucket[i+j]); nb = 0; i += group_size; } diff --git a/VNFs/DPPD-PROX/handle_lat.h b/VNFs/DPPD-PROX/handle_lat.h index da164656..a80afc90 100644 --- a/VNFs/DPPD-PROX/handle_lat.h +++ b/VNFs/DPPD-PROX/handle_lat.h @@ -29,6 +29,9 @@ // packet N is received (re-ordering) resulting in accuracy being unused // 8192 packets is equivalent to 550 micro-seconds at 10Gbps for 64 bytes packets #define ACCURACY_WINDOW 8192 +#define LAT_BUCKET_COUNT 128 + +#define LAT_BUCKET_COUNT 128 #define LAT_BUCKET_COUNT 128 -- cgit 1.2.3-korg