2 // Copyright (c) 2010-2019 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;
28 struct lat_test lat_test;
29 struct lat_test tot_lat_test;
30 struct stats_latency stats;
31 struct stats_latency tot;
34 struct stats_latency_manager {
37 struct stats_latency_manager_entry entries[0]; /* copy of stats when running update stats. */
40 static struct stats_latency_manager *slm;
42 void stats_latency_reset(void)
44 for (uint16_t i = 0; i < slm->n_latency; ++i)
45 lat_test_reset(&slm->entries[i].tot_lat_test);
48 int stats_get_n_latency(void)
50 return slm->n_latency;
53 int stats_get_latency_bucket_size(void)
55 return slm->bucket_size;
58 uint32_t stats_latency_get_core_id(uint32_t i)
60 return slm->entries[i].lcore_id;
63 uint32_t stats_latency_get_task_id(uint32_t i)
65 return slm->entries[i].task_id;
68 struct stats_latency *stats_latency_get(uint32_t i)
70 return &slm->entries[i].stats;
73 uint64_t *stats_latency_get_bucket(uint32_t i)
75 return slm->entries[i].lat_test.buckets;
78 uint64_t *stats_latency_get_tot_bucket(uint32_t i)
80 return slm->entries[i].tot_lat_test.buckets;
83 struct stats_latency *stats_latency_tot_get(uint32_t i)
85 return &slm->entries[i].tot;
88 static struct stats_latency_manager_entry *stats_latency_entry_find(uint8_t lcore_id, uint8_t task_id)
90 struct stats_latency_manager_entry *entry;
92 for (uint16_t i = 0; i < stats_get_n_latency(); ++i) {
93 entry = &slm->entries[i];
95 if (entry->lcore_id == lcore_id && entry->task_id == task_id) {
102 struct stats_latency *stats_latency_tot_find(uint32_t lcore_id, uint32_t task_id)
104 struct stats_latency_manager_entry *entry = stats_latency_entry_find(lcore_id, task_id);
112 struct stats_latency *stats_latency_find(uint32_t lcore_id, uint32_t task_id)
114 struct stats_latency_manager_entry *entry = stats_latency_entry_find(lcore_id, task_id);
119 return &entry->stats;
122 static int task_runs_observable_latency(struct task_args *targ)
124 /* Note that multiple ports or rings are only supported
125 if they all receive packets configured in the same way
126 e.g. same timestamp pos. */
127 return !strcmp(targ->task_init->mode_str, "lat") &&
128 (targ->nb_rxports >= 1 || targ->nb_rxrings >= 1);
131 static struct stats_latency_manager *alloc_stats_latency_manager(void)
133 const uint32_t socket_id = rte_lcore_to_socket_id(rte_lcore_id());
134 struct stats_latency_manager *ret;
135 struct lcore_cfg *lconf;
136 uint32_t n_latency = 0;
141 while (prox_core_next(&lcore_id, 0) == 0) {
142 lconf = &lcore_cfg[lcore_id];
143 for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
144 struct task_args *targ = &lconf->targs[task_id];
145 if (task_runs_observable_latency(targ))
149 mem_size = sizeof(*ret) + sizeof(ret->entries[0]) * n_latency;
151 ret = prox_zmalloc(mem_size, socket_id);
155 static void stats_latency_add_task(struct lcore_cfg *lconf, struct task_args *targ)
157 struct stats_latency_manager_entry *new_entry = &slm->entries[slm->n_latency];
159 new_entry->task = (struct task_lat *)targ->tbase;
160 new_entry->bucket_size = task_lat_get_latency_bucket_size(new_entry->task);
161 new_entry->lcore_id = lconf->id;
162 new_entry->task_id = targ->id;
163 new_entry->tot_lat_test.min_lat = -1;
164 if (slm->bucket_size == 0)
165 slm->bucket_size = new_entry->bucket_size;
166 else if (slm->bucket_size != new_entry->bucket_size)
167 plog_err("Latency bucket size does not support different bucket sizes per task - using bucket size from first task (%d)\n", slm->bucket_size);
171 void stats_latency_init(void)
173 struct lcore_cfg *lconf = NULL;
174 struct task_args *targ;
176 slm = alloc_stats_latency_manager();
178 while (core_targ_next(&lconf, &targ, 0) == 0) {
179 if (task_runs_observable_latency(targ))
180 stats_latency_add_task(lconf, targ);
184 #ifdef LATENCY_HISTOGRAM
185 void stats_core_lat_histogram(uint8_t lcore_id, uint8_t task_id, uint64_t **buckets)
187 struct stats_latency_manager_entry *lat_stats;
190 lat_stats = stats_latency_entry_find(lcore_id, task_id);
193 *buckets = lat_stats->lat_test.buckets;
199 static void stats_latency_fetch_entry(struct stats_latency_manager_entry *entry)
201 struct stats_latency *cur = &entry->stats;
202 struct lat_test *lat_test_local = &entry->lat_test;
203 struct lat_test *lat_test_remote = task_lat_get_latency_meassurement(entry->task);
205 if (!lat_test_remote)
208 if (lat_test_remote->tot_all_pkts) {
209 lat_test_copy(&entry->lat_test, lat_test_remote);
210 lat_test_reset(lat_test_remote);
211 lat_test_combine(&entry->tot_lat_test, &entry->lat_test);
214 task_lat_use_other_latency_meassurement(entry->task);
217 static void stats_latency_from_lat_test(struct stats_latency *dst, struct lat_test *src)
219 /* In case packets were received, but measurements were too
222 dst->max = lat_test_get_max(src);
223 dst->min = lat_test_get_min(src);
224 dst->avg = lat_test_get_avg(src);
225 dst->stddev = lat_test_get_stddev(src);
227 dst->accuracy_limit = lat_test_get_accuracy_limit(src);
228 dst->tot_packets = src->tot_pkts;
229 dst->tot_all_packets = src->tot_all_pkts;
230 dst->lost_packets = src->lost_packets;
231 dst->mis_ordered = src->mis_ordered;
232 dst->extent = src->extent;
233 dst->duplicate = src->duplicate;
236 static void stats_latency_update_entry(struct stats_latency_manager_entry *entry)
238 if (!entry->lat_test.tot_all_pkts)
241 stats_latency_from_lat_test(&entry->stats, &entry->lat_test);
242 stats_latency_from_lat_test(&entry->tot, &entry->tot_lat_test);
245 void stats_latency_update(void)
247 for (uint16_t i = 0; i < slm->n_latency; ++i)
248 stats_latency_fetch_entry(&slm->entries[i]);
249 for (uint16_t i = 0; i < slm->n_latency; ++i)
250 stats_latency_update_entry(&slm->entries[i]);