2 // Copyright (c) 2010-2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
17 #include "prox_malloc.h"
18 #include "stats_latency.h"
19 #include "handle_lat.h"
21 #include "prox_args.h"
23 struct stats_latency_manager_entry {
24 struct task_lat *task;
27 struct lat_test lat_test;
28 struct lat_test tot_lat_test;
29 struct stats_latency stats;
30 struct stats_latency tot;
33 struct stats_latency_manager {
35 struct stats_latency_manager_entry entries[0]; /* copy of stats when running update stats. */
38 static struct stats_latency_manager *slm;
40 void stats_latency_reset(void)
42 for (uint16_t i = 0; i < slm->n_latency; ++i)
43 lat_test_reset(&slm->entries[i].tot_lat_test);
46 int stats_get_n_latency(void)
48 return slm->n_latency;
51 uint32_t stats_latency_get_core_id(uint32_t i)
53 return slm->entries[i].lcore_id;
56 uint32_t stats_latency_get_task_id(uint32_t i)
58 return slm->entries[i].task_id;
61 struct stats_latency *stats_latency_get(uint32_t i)
63 return &slm->entries[i].stats;
66 struct stats_latency *stats_latency_tot_get(uint32_t i)
68 return &slm->entries[i].tot;
71 static struct stats_latency_manager_entry *stats_latency_entry_find(uint8_t lcore_id, uint8_t task_id)
73 struct stats_latency_manager_entry *entry;
75 for (uint16_t i = 0; i < stats_get_n_latency(); ++i) {
76 entry = &slm->entries[i];
78 if (entry->lcore_id == lcore_id && entry->task_id == task_id) {
85 struct stats_latency *stats_latency_tot_find(uint32_t lcore_id, uint32_t task_id)
87 struct stats_latency_manager_entry *entry = stats_latency_entry_find(lcore_id, task_id);
95 struct stats_latency *stats_latency_find(uint32_t lcore_id, uint32_t task_id)
97 struct stats_latency_manager_entry *entry = stats_latency_entry_find(lcore_id, task_id);
102 return &entry->stats;
105 static int task_runs_observable_latency(struct task_args *targ)
107 /* TODO: make this work with multiple ports and with
108 rings. Currently, only showing lat tasks which have 1 RX
110 return !strcmp(targ->task_init->mode_str, "lat") &&
111 (targ->nb_rxports == 1 || targ->nb_rxrings == 1);
114 static struct stats_latency_manager *alloc_stats_latency_manager(void)
116 const uint32_t socket_id = rte_lcore_to_socket_id(rte_lcore_id());
117 struct stats_latency_manager *ret;
118 struct lcore_cfg *lconf;
119 uint32_t n_latency = 0;
124 while (prox_core_next(&lcore_id, 0) == 0) {
125 lconf = &lcore_cfg[lcore_id];
126 for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
127 struct task_args *targ = &lconf->targs[task_id];
128 if (task_runs_observable_latency(targ))
132 mem_size = sizeof(*ret) + sizeof(ret->entries[0]) * n_latency;
134 ret = prox_zmalloc(mem_size, socket_id);
138 static void stats_latency_add_task(struct lcore_cfg *lconf, struct task_args *targ)
140 struct stats_latency_manager_entry *new_entry = &slm->entries[slm->n_latency];
142 new_entry->task = (struct task_lat *)targ->tbase;
143 new_entry->lcore_id = lconf->id;
144 new_entry->task_id = targ->id;
148 void stats_latency_init(void)
150 struct lcore_cfg *lconf = NULL;
151 struct task_args *targ;
153 slm = alloc_stats_latency_manager();
155 while (core_targ_next(&lconf, &targ, 0) == 0) {
156 if (task_runs_observable_latency(targ))
157 stats_latency_add_task(lconf, targ);
161 #ifdef LATENCY_HISTOGRAM
162 void stats_core_lat_histogram(uint8_t lcore_id, uint8_t task_id, uint64_t **buckets)
164 struct stats_latency_manager_entry *lat_stats;
167 lat_stats = stats_latency_entry_find(lcore_id, task_id);
170 *buckets = lat_stats->lat_test.buckets;
176 static void stats_latency_fetch_entry(struct stats_latency_manager_entry *entry)
178 struct stats_latency *cur = &entry->stats;
179 struct lat_test *lat_test_local = &entry->lat_test;
180 struct lat_test *lat_test_remote = task_lat_get_latency_meassurement(entry->task);
182 if (!lat_test_remote)
185 if (lat_test_remote->tot_all_pkts) {
186 lat_test_copy(&entry->lat_test, lat_test_remote);
187 lat_test_reset(lat_test_remote);
188 lat_test_combine(&entry->tot_lat_test, &entry->lat_test);
191 task_lat_use_other_latency_meassurement(entry->task);
194 static void stats_latency_from_lat_test(struct stats_latency *dst, struct lat_test *src)
196 /* In case packets were received, but measurements were too
199 dst->max = lat_test_get_max(src);
200 dst->min = lat_test_get_min(src);
201 dst->avg = lat_test_get_avg(src);
202 dst->stddev = lat_test_get_stddev(src);
204 dst->accuracy_limit = lat_test_get_accuracy_limit(src);
205 dst->tot_packets = src->tot_pkts;
206 dst->tot_all_packets = src->tot_all_pkts;
207 dst->lost_packets = src->lost_packets;
210 static void stats_latency_update_entry(struct stats_latency_manager_entry *entry)
212 if (!entry->lat_test.tot_all_pkts)
215 stats_latency_from_lat_test(&entry->stats, &entry->lat_test);
216 stats_latency_from_lat_test(&entry->tot, &entry->tot_lat_test);
219 void stats_latency_update(void)
221 for (uint16_t i = 0; i < slm->n_latency; ++i)
222 stats_latency_fetch_entry(&slm->entries[i]);
223 for (uint16_t i = 0; i < slm->n_latency; ++i)
224 stats_latency_update_entry(&slm->entries[i]);