/* // Copyright (c) 2010-2017 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. */ #include #include "stats_task.h" #include "prox_cfg.h" #include "prox_globals.h" #include "lconf.h" struct lcore_task_stats { struct task_stats task_stats[MAX_TASKS_PER_CORE]; }; #define TASK_STATS_RX 0x01 #define TASK_STATS_TX 0x02 extern int last_stat; static struct lcore_task_stats lcore_task_stats_all[RTE_MAX_LCORE]; static struct task_stats *task_stats_set[RTE_MAX_LCORE * MAX_TASKS_PER_CORE]; static uint8_t nb_tasks_tot; int stats_get_n_tasks_tot(void) { return nb_tasks_tot; } struct task_stats *stats_get_task_stats(uint32_t lcore_id, uint32_t task_id) { return &lcore_task_stats_all[lcore_id].task_stats[task_id]; } struct task_stats_sample *stats_get_task_stats_sample(uint32_t lcore_id, uint32_t task_id, int l) { return &lcore_task_stats_all[lcore_id].task_stats[task_id].sample[l == last_stat]; } void stats_task_reset(void) { struct task_stats *cur_task_stats; for (uint8_t task_id = 0; task_id < nb_tasks_tot; ++task_id) { cur_task_stats = task_stats_set[task_id]; cur_task_stats->tot_rx_pkt_count = 0; cur_task_stats->tot_tx_pkt_count = 0; cur_task_stats->tot_drop_tx_fail = 0; cur_task_stats->tot_drop_discard = 0; cur_task_stats->tot_drop_handled = 0; } } uint64_t stats_core_task_tot_rx(uint8_t lcore_id, uint8_t task_id) { return lcore_task_stats_all[lcore_id].task_stats[task_id].tot_rx_pkt_count; } uint64_t stats_core_task_tot_tx(uint8_t lcore_id, uint8_t task_id) { return lcore_task_stats_all[lcore_id].task_stats[task_id].tot_tx_pkt_count; } uint64_t stats_core_task_tot_drop(uint8_t lcore_id, uint8_t task_id) { return lcore_task_stats_all[lcore_id].task_stats[task_id].tot_drop_tx_fail + lcore_task_stats_all[lcore_id].task_stats[task_id].tot_drop_discard + lcore_task_stats_all[lcore_id].task_stats[task_id].tot_drop_handled; } uint64_t stats_core_task_last_tsc(uint8_t lcore_id, uint8_t task_id) { return lcore_task_stats_all[lcore_id].task_stats[task_id].sample[last_stat].tsc; } static void init_core_port(struct task_stats *ts, struct task_rt_stats *stats, uint8_t flags) { ts->stats = stats; ts->flags |= flags; } void stats_task_post_proc(void) { for (uint8_t task_id = 0; task_id < nb_tasks_tot; ++task_id) { struct task_stats *cur_task_stats = task_stats_set[task_id]; const struct task_stats_sample *last = &cur_task_stats->sample[last_stat]; const struct task_stats_sample *prev = &cur_task_stats->sample[!last_stat]; /* no total stats for empty loops */ cur_task_stats->tot_rx_pkt_count += last->rx_pkt_count - prev->rx_pkt_count; cur_task_stats->tot_tx_pkt_count += last->tx_pkt_count - prev->tx_pkt_count; cur_task_stats->tot_drop_tx_fail += last->drop_tx_fail - prev->drop_tx_fail; cur_task_stats->tot_drop_discard += last->drop_discard - prev->drop_discard; cur_task_stats->tot_drop_handled += last->drop_handled - prev->drop_handled; } } void stats_task_update(void) { uint64_t before, after; for (uint8_t task_id = 0; task_id < nb_tasks_tot; ++task_id) { struct task_stats *cur_task_stats = task_stats_set[task_id]; struct task_rt_stats *stats = cur_task_stats->stats; struct task_stats_sample *last = &cur_task_stats->sample[last_stat]; /* Read TX first and RX second, in order to prevent displaying a negative packet loss. Depending on the configuration (when forwarding, for example), TX might be bigger than RX. */ before = rte_rdtsc(); last->tx_pkt_count = stats->tx_pkt_count; last->drop_tx_fail = stats->drop_tx_fail; last->drop_discard = stats->drop_discard; last->drop_handled = sta