summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/stats_latency.c
diff options
context:
space:
mode:
Diffstat (limited to 'VNFs/DPPD-PROX/stats_latency.c')
-rw-r--r--VNFs/DPPD-PROX/stats_latency.c225
1 files changed, 225 insertions, 0 deletions
diff --git a/VNFs/DPPD-PROX/stats_latency.c b/VNFs/DPPD-PROX/stats_latency.c
new file mode 100644
index 00000000..52027892
--- /dev/null
+++ b/VNFs/DPPD-PROX/stats_latency.c
@@ -0,0 +1,225 @@
+/*
+// 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 "prox_malloc.h"
+#include "stats_latency.h"
+#include "handle_lat.h"
+#include "prox_cfg.h"
+#include "prox_args.h"
+
+struct stats_latency_manager_entry {
+ struct task_lat *task;
+ uint8_t lcore_id;
+ uint8_t task_id;
+ struct lat_test lat_test;
+ struct lat_test tot_lat_test;
+ struct stats_latency stats;
+ struct stats_latency tot;
+};
+
+struct stats_latency_manager {
+ uint16_t n_latency;
+ struct stats_latency_manager_entry entries[0]; /* copy of stats when running update stats. */
+};
+
+static struct stats_latency_manager *slm;
+
+void stats_latency_reset(void)
+{
+ for (uint16_t i = 0; i < slm->n_latency; ++i)
+ lat_test_reset(&slm->entries[i].tot_lat_test);
+}
+
+int stats_get_n_latency(void)
+{
+ return slm->n_latency;
+}
+
+uint32_t stats_latency_get_core_id(uint32_t i)
+{
+ return slm->entries[i].lcore_id;
+}
+
+uint32_t stats_latency_get_task_id(uint32_t i)
+{
+ return slm->entries[i].task_id;
+}
+
+struct stats_latency *stats_latency_get(uint32_t i)
+{
+ return &slm->entries[i].stats;
+}
+
+struct stats_latency *stats_latency_tot_get(uint32_t i)
+{
+ return &slm->entries[i].tot;
+}
+
+static struct stats_latency_manager_entry *stats_latency_entry_find(uint8_t lcore_id, uint8_t task_id)
+{
+ struct stats_latency_manager_entry *entry;
+
+ for (uint16_t i = 0; i < stats_get_n_latency(); ++i) {
+ entry = &slm->entries[i];
+
+ if (entry->lcore_id == lcore_id && entry->task_id == task_id) {
+ return entry;
+ }
+ }
+ return NULL;
+}
+
+struct stats_latency *stats_latency_tot_find(uint32_t lcore_id, uint32_t task_id)
+{
+ struct stats_latency_manager_entry *entry = stats_latency_entry_find(lcore_id, task_id);
+
+ if (!entry)
+ return NULL;
+ else
+ return &entry->tot;
+}
+
+struct stats_latency *stats_latency_find(uint32_t lcore_id, uint32_t task_id)
+{
+ struct stats_latency_manager_entry *entry = stats_latency_entry_find(lcore_id, task_id);
+
+ if (!entry)
+ return NULL;
+ else
+ return &entry->stats;
+}
+
+static int task_runs_observable_latency(struct task_args *targ)
+{
+ /* TODO: make this work with multiple ports and with
+ rings. Currently, only showing lat tasks which have 1 RX
+ port. */
+ return !strcmp(targ->task_init->mode_str, "lat") &&
+ (targ->nb_rxports == 1 || targ->nb_rxrings == 1);
+}
+
+static struct stats_latency_manager *alloc_stats_latency_manager(void)
+{
+ const uint32_t socket_id = rte_lcore_to_socket_id(rte_lcore_id());
+ struct stats_latency_manager *ret;
+ struct lcore_cfg *lconf;
+ uint32_t n_latency = 0;
+ uint32_t lcore_id;
+ size_t mem_size;
+
+ lcore_id = -1;
+ while (prox_core_next(&lcore_id, 0) == 0) {
+ lconf = &lcore_cfg[lcore_id];
+ for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+ struct task_args *targ = &lconf->targs[task_id];
+ if (task_runs_observable_latency(targ))
+ ++n_latency;
+ }
+ }
+ mem_size = sizeof(*ret) + sizeof(ret->entries[0]) * n_latency;
+
+ ret = prox_zmalloc(mem_size, socket_id);
+ return ret;
+}
+
+static void stats_latency_add_task(struct lcore_cfg *lconf, struct task_args *targ)
+{
+ struct stats_latency_manager_entry *new_entry = &slm->entries[slm->n_latency];
+
+ new_entry->task = (struct task_lat *)targ->tbase;
+ new_entry->lcore_id = lconf->id;
+ new_entry->task_id = targ->id;
+ slm->n_latency++;
+}
+
+void stats_latency_init(void)
+{
+ struct lcore_cfg *lconf = NULL;
+ struct task_args *targ;
+
+ slm = alloc_stats_latency_manager();
+
+ while (core_targ_next(&lconf, &targ, 0) == 0) {
+ if (task_runs_observable_latency(targ))
+ stats_latency_add_task(lconf, targ);
+ }
+}
+
+#ifdef LATENCY_HISTOGRAM
+void stats_core_lat_histogram(uint8_t lcore_id, uint8_t task_id, uint64_t **buckets)
+{
+ struct stats_latency_manager_entry *lat_stats;
+ uint64_t tsc;
+
+ lat_stats = stats_latency_entry_find(lcore_id, task_id);
+
+ if (lat_stats)
+ *buckets = lat_stats->lat_test.buckets;
+ else
+ *buckets = NULL;
+}
+#endif
+
+static void stats_latency_fetch_entry(struct stats_latency_manager_entry *entry)
+{
+ struct stats_latency *cur = &entry->stats;
+ struct lat_test *lat_test_local = &entry->lat_test;
+ struct lat_test *lat_test_remote = task_lat_get_latency_meassurement(entry->task);
+
+ if (!lat_test_remote)
+ return;
+
+ if (lat_test_remote->tot_all_pkts) {
+ lat_test_copy(&entry->lat_test, lat_test_remote);
+ lat_test_reset(lat_test_remote);
+ lat_test_combine(&entry->tot_lat_test, &entry->lat_test);
+ }
+
+ task_lat_use_other_latency_meassurement(entry->task);
+}
+
+static void stats_latency_from_lat_test(struct stats_latency *dst, struct lat_test *src)
+{
+ /* In case packets were received, but measurements were too
+ inaccurate */
+ if (src->tot_pkts) {
+ dst->max = lat_test_get_max(src);
+ dst->min = lat_test_get_min(src);
+ dst->avg = lat_test_get_avg(src);
+ dst->stddev = lat_test_get_stddev(src);
+ }
+ dst->accuracy_limit = lat_test_get_accuracy_limit(src);
+ dst->tot_packets = src->tot_pkts;
+ dst->tot_all_packets = src->tot_all_pkts;
+ dst->lost_packets = src->lost_packets;
+}
+
+static void stats_latency_update_entry(struct stats_latency_manager_entry *entry)
+{
+ if (!entry->lat_test.tot_all_pkts)
+ return;
+
+ stats_latency_from_lat_test(&entry->stats, &entry->lat_test);
+ stats_latency_from_lat_test(&entry->tot, &entry->tot_lat_test);
+}
+
+void stats_latency_update(void)
+{
+ for (uint16_t i = 0; i < slm->n_latency; ++i)
+ stats_latency_fetch_entry(&slm->entries[i]);
+ for (uint16_t i = 0; i < slm->n_latency; ++i)
+ stats_latency_update_entry(&slm->entries[i]);
+}