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 <rte_cycles.h>
20 #include "stats_l4gen.h"
21 #include "stats_cons_log.h"
23 #include "prox_args.h"
24 #include "prox_assert.h"
27 static struct stats_cons stats_cons_log = {
28 .init = stats_cons_log_init,
29 .notify = stats_cons_log_notify,
30 .finish = stats_cons_log_finish,
32 .flags = STATS_CONS_F_ALL,
34 .flags = STATS_CONS_F_PORTS|STATS_CONS_F_TASKS,
42 uint64_t n_entry_fields;
43 uint8_t n_entry_field_size[64];
46 static void header_init(struct header *hdr, uint64_t hz, uint64_t now, uint64_t n_entries) {
47 memset(hdr, 0, sizeof(*hdr));
50 hdr->n_entries = n_entries;
53 static void header_add_field(struct header *hdr, uint8_t size) {
54 hdr->n_entry_field_size[hdr->n_entry_fields++] = size;
57 static void header_write(struct header *hdr, FILE *fp) {
58 size_t header_size_no_fields = sizeof(*hdr) - sizeof(hdr->n_entry_field_size);
59 size_t header_size_effective = header_size_no_fields + hdr->n_entry_fields;
61 fwrite(hdr, header_size_effective, 1, fp);
64 #define BUFFERED_RECORD_LEN 16384
66 #define STATS_DUMP_FILE_NAME "stats_dump"
77 static struct entry entries[64];
78 static uint64_t n_entries;
84 uint64_t active_connections;
85 uint64_t bundles_created;
89 } __attribute__((packed));
98 } __attribute__((packed));
101 static struct record buf[BUFFERED_RECORD_LEN];
102 static size_t buf_pos = 0;
104 struct stats_cons *stats_cons_log_get(void)
106 return &stats_cons_log;
110 void stats_cons_log_init(void)
112 fp = fopen(STATS_DUMP_FILE_NAME, "w");
116 uint32_t lcore_id = -1;
118 while(prox_core_next(&lcore_id, 0) == 0) {
119 struct lcore_cfg *lconf = &lcore_cfg[lcore_id];
121 if (lconf->n_tasks_all && (strcmp(lconf->targs[0].task_init->mode_str, "genl4") ||
122 strcmp(lconf->targs[0].task_init->sub_mode_str, "")))
125 for (uint32_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
126 entries[n_entries].lcore_id = lcore_id;
127 entries[n_entries].task_id = task_id;
128 entries[n_entries].l4_stats_id = n_entries;
130 if (n_entries == sizeof(entries)/sizeof(entries[0]))
133 cmd_rx_bw_start(lcore_id);
134 cmd_tx_bw_start(lcore_id);
135 if (n_entries == sizeof(entries)/sizeof(entries[0]))
141 header_init(&hdr, rte_get_tsc_hz(), rte_rdtsc(), n_entries);
142 header_add_field(&hdr, sizeof(((struct record *)0)->lcore_id));
143 header_add_field(&hdr, sizeof(((struct record *)0)->task_id));
144 header_add_field(&hdr, sizeof(((struct record *)0)->active_connections));
145 header_add_field(&hdr, sizeof(((struct record *)0)->bundles_created));
146 header_add_field(&hdr, sizeof(((struct record *)0)->rx_bytes));
147 header_add_field(&hdr, sizeof(((struct record *)0)->tx_bytes));
148 header_add_field(&hdr, sizeof(((struct record *)0)->tsc));
150 header_write(&hdr, fp);
153 void stats_cons_log_notify(void)
155 const uint32_t n_l4gen = stats_get_n_l4gen();
157 if (buf_pos + n_entries > sizeof(buf)/sizeof(buf[0])) {
158 fwrite(buf, sizeof(buf[0]), buf_pos, fp);
161 PROX_ASSERT(buf_pos + n_entries <= sizeof(buf)/sizeof(buf[0]));
163 for (uint32_t i = 0; i < n_entries; ++i) {
164 uint32_t c = entries[i].lcore_id;
165 uint32_t t = entries[i].task_id;
166 uint32_t j = entries[i].l4_stats_id;
167 struct l4_stats_sample *clast = stats_get_l4_stats_sample(j, 1);
168 struct task_stats *l = stats_get_task_stats(c, t);
169 struct task_stats_sample *last = stats_get_task_stats_sample(c, t, 1);
171 buf[buf_pos].lcore_id = c;
172 buf[buf_pos].task_id = t;
174 uint64_t tot_created = clast->stats.tcp_created + clast->stats.udp_created;
175 uint64_t tot_finished = clast->stats.tcp_finished_retransmit + clast->stats.tcp_finished_no_retransmit +
176 clast->stats.udp_finished + clast->stats.udp_expired + clast->stats.tcp_expired;
178 buf[buf_pos].active_connections = tot_created - tot_finished;
179 buf[buf_pos].bundles_created = clast->stats.bundles_created;
180 buf[buf_pos].rx_bytes = last->rx_bytes;
181 buf[buf_pos].tx_bytes = last->tx_bytes;
182 buf[buf_pos].tsc = clast->tsc;
189 void stats_cons_log_init(void)
191 uint64_t el = rte_get_tsc_hz();
192 uint64_t now = rte_rdtsc();
194 fp = fopen(STATS_DUMP_FILE_NAME, "w");
198 uint32_t lcore_id = -1;
200 while(prox_core_next(&lcore_id, 0) == 0) {
201 struct lcore_cfg *lconf = &lcore_cfg[lcore_id];
203 if (!lconf->n_tasks_all)
206 for (uint32_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
207 if (strcmp(lconf->targs[task_id].task_init->mode_str, "lbpos"))
210 entries[n_entries].lcore_id = lcore_id;
211 entries[n_entries].task_id = task_id;
213 if (n_entries == sizeof(entries)/sizeof(entries[0]))
216 cmd_rx_bw_start(lcore_id);
217 cmd_tx_bw_start(lcore_id);
218 if (n_entries == sizeof(entries)/sizeof(entries[0]))
224 header_init(&hdr, rte_get_tsc_hz(), rte_rdtsc(), n_entries);
225 header_add_field(&hdr, sizeof(((struct record *)0)->lcore_id));
226 header_add_field(&hdr, sizeof(((struct record *)0)->task_id));
227 header_add_field(&hdr, sizeof(((struct record *)0)->rx_bytes));
228 header_add_field(&hdr, sizeof(((struct record *)0)->tx_bytes));
229 header_add_field(&hdr, sizeof(((struct record *)0)->drop_bytes));
230 header_add_field(&hdr, sizeof(((struct record *)0)->tsc));
231 header_write(&hdr, fp);
234 void stats_cons_log_notify(void)
236 for (uint32_t i = 0; i < n_entries; ++i) {
237 uint32_t c = entries[i].lcore_id;
238 uint32_t t = entries[i].task_id;
239 struct task_stats *l = stats_get_task_stats(c, t);
240 struct task_stats_sample *last = stats_get_task_stats_sample(c, t, 1);
242 buf[buf_pos].lcore_id = c;
243 buf[buf_pos].task_id = t;
244 buf[buf_pos].tx_bytes = last->tx_bytes;
245 buf[buf_pos].rx_bytes = last->rx_bytes;
246 buf[buf_pos].drop_bytes = last->drop_bytes;
247 /* buf[buf_pos].drop_tx_fail = l->tot_drop_tx_fail; */
248 buf[buf_pos].tsc = last->tsc;
252 if (buf_pos == sizeof(buf)/sizeof(buf[0])) {
253 fwrite(buf, sizeof(buf), 1, fp);
260 void stats_cons_log_finish(void)
264 fwrite(buf, sizeof(buf[0]), buf_pos, fp);