summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/stats_cons_log.c
diff options
context:
space:
mode:
Diffstat (limited to 'VNFs/DPPD-PROX/stats_cons_log.c')
-rw-r--r--VNFs/DPPD-PROX/stats_cons_log.c269
1 files changed, 269 insertions, 0 deletions
diff --git a/VNFs/DPPD-PROX/stats_cons_log.c b/VNFs/DPPD-PROX/stats_cons_log.c
new file mode 100644
index 00000000..7e966533
--- /dev/null
+++ b/VNFs/DPPD-PROX/stats_cons_log.c
@@ -0,0 +1,269 @@
+/*
+// 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 <rte_cycles.h>
+
+#include "stats.h"
+#include "stats_l4gen.h"
+#include "stats_cons_log.h"
+#include "prox_cfg.h"
+#include "prox_args.h"
+#include "prox_assert.h"
+#include "commands.h"
+
+static struct stats_cons stats_cons_log = {
+ .init = stats_cons_log_init,
+ .notify = stats_cons_log_notify,
+ .finish = stats_cons_log_finish,
+#ifndef DPI_STATS
+ .flags = STATS_CONS_F_ALL,
+#else
+ .flags = STATS_CONS_F_PORTS|STATS_CONS_F_TASKS,
+#endif
+};
+
+struct header {
+ uint64_t hz;
+ uint64_t now;
+ uint64_t n_entries;
+ uint64_t n_entry_fields;
+ uint8_t n_entry_field_size[64];
+};
+
+static void header_init(struct header *hdr, uint64_t hz, uint64_t now, uint64_t n_entries) {
+ memset(hdr, 0, sizeof(*hdr));
+ hdr->hz = hz;
+ hdr->now = now;
+ hdr->n_entries = n_entries;
+}
+
+static void header_add_field(struct header *hdr, uint8_t size) {
+ hdr->n_entry_field_size[hdr->n_entry_fields++] = size;
+}
+
+static void header_write(struct header *hdr, FILE *fp) {
+ size_t header_size_no_fields = sizeof(*hdr) - sizeof(hdr->n_entry_field_size);
+ size_t header_size_effective = header_size_no_fields + hdr->n_entry_fields;
+
+ fwrite(hdr, header_size_effective, 1, fp);
+}
+
+#define BUFFERED_RECORD_LEN 16384
+
+#define STATS_DUMP_FILE_NAME "stats_dump"
+static FILE *fp;
+
+struct entry {
+ uint32_t lcore_id;
+ uint32_t task_id;
+#ifndef DPI_STATS
+ uint32_t l4_stats_id;
+#endif
+};
+
+static struct entry entries[64];
+static uint64_t n_entries;
+
+#ifndef DPI_STATS
+struct record {
+ uint32_t lcore_id;
+ uint32_t task_id;
+ uint64_t active_connections;
+ uint64_t bundles_created;
+ uint64_t rx_bytes;
+ uint64_t tx_bytes;
+ uint64_t tsc;
+} __attribute__((packed));
+#else
+struct record {
+ uint32_t lcore_id;
+ uint32_t task_id;
+ uint64_t rx_bytes;
+ uint64_t tx_bytes;
+ uint64_t drop_bytes;
+ uint64_t tsc;
+} __attribute__((packed));
+#endif
+
+static struct record buf[BUFFERED_RECORD_LEN];
+static size_t buf_pos = 0;
+
+struct stats_cons *stats_cons_log_get(void)
+{
+ return &stats_cons_log;
+}
+
+#ifndef DPI_STATS
+void stats_cons_log_init(void)
+{
+ fp = fopen(STATS_DUMP_FILE_NAME, "w");
+ if (!fp)
+ return;
+
+ uint32_t lcore_id = -1;
+
+ while(prox_core_next(&lcore_id, 0) == 0) {
+ struct lcore_cfg *lconf = &lcore_cfg[lcore_id];
+
+ if (lconf->n_tasks_all && (strcmp(lconf->targs[0].task_init->mode_str, "genl4") ||
+ strcmp(lconf->targs[0].task_init->sub_mode_str, "")))
+ continue;
+
+ for (uint32_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+ entries[n_entries].lcore_id = lcore_id;
+ entries[n_entries].task_id = task_id;
+ entries[n_entries].l4_stats_id = n_entries;
+ n_entries++;
+ if (n_entries == sizeof(entries)/sizeof(entries[0]))
+ break;
+ }
+ cmd_rx_bw_start(lcore_id);
+ cmd_tx_bw_start(lcore_id);
+ if (n_entries == sizeof(entries)/sizeof(entries[0]))
+ break;
+ }
+
+ struct header hdr;
+
+ header_init(&hdr, rte_get_tsc_hz(), rte_rdtsc(), n_entries);
+ header_add_field(&hdr, sizeof(((struct record *)0)->lcore_id));
+ header_add_field(&hdr, sizeof(((struct record *)0)->task_id));
+ header_add_field(&hdr, sizeof(((struct record *)0)->active_connections));
+ header_add_field(&hdr, sizeof(((struct record *)0)->bundles_created));
+ header_add_field(&hdr, sizeof(((struct record *)0)->rx_bytes));
+ header_add_field(&hdr, sizeof(((struct record *)0)->tx_bytes));
+ header_add_field(&hdr, sizeof(((struct record *)0)->tsc));
+
+ header_write(&hdr, fp);
+}
+
+void stats_cons_log_notify(void)
+{
+ const uint32_t n_l4gen = stats_get_n_l4gen();
+
+ if (buf_pos + n_entries > sizeof(buf)/sizeof(buf[0])) {
+ fwrite(buf, sizeof(buf[0]), buf_pos, fp);
+ buf_pos = 0;
+ }
+ PROX_ASSERT(buf_pos + n_entries <= sizeof(buf)/sizeof(buf[0]));
+
+ for (uint32_t i = 0; i < n_entries; ++i) {
+ uint32_t c = entries[i].lcore_id;
+ uint32_t t = entries[i].task_id;
+ uint32_t j = entries[i].l4_stats_id;
+ struct l4_stats_sample *clast = stats_get_l4_stats_sample(j, 1);
+ struct task_stats *l = stats_get_task_stats(c, t);
+ struct task_stats_sample *last = stats_get_task_stats_sample(c, t, 1);
+
+ buf[buf_pos].lcore_id = c;
+ buf[buf_pos].task_id = t;
+
+ uint64_t tot_created = clast->stats.tcp_created + clast->stats.udp_created;
+ uint64_t tot_finished = clast->stats.tcp_finished_retransmit + clast->stats.tcp_finished_no_retransmit +
+ clast->stats.udp_finished + clast->stats.udp_expired + clast->stats.tcp_expired;
+
+ buf[buf_pos].active_connections = tot_created - tot_finished;
+ buf[buf_pos].bundles_created = clast->stats.bundles_created;
+ buf[buf_pos].rx_bytes = last->rx_bytes;
+ buf[buf_pos].tx_bytes = last->tx_bytes;
+ buf[buf_pos].tsc = clast->tsc;
+
+ buf_pos++;
+ }
+}
+
+#else
+void stats_cons_log_init(void)
+{
+ uint64_t el = rte_get_tsc_hz();
+ uint64_t now = rte_rdtsc();
+
+ fp = fopen(STATS_DUMP_FILE_NAME, "w");
+ if (!fp)
+ return;
+
+ uint32_t lcore_id = -1;
+
+ while(prox_core_next(&lcore_id, 0) == 0) {
+ struct lcore_cfg *lconf = &lcore_cfg[lcore_id];
+
+ if (!lconf->n_tasks_all)
+ continue;
+
+ for (uint32_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+ if (strcmp(lconf->targs[task_id].task_init->mode_str, "lbpos"))
+ continue;
+
+ entries[n_entries].lcore_id = lcore_id;
+ entries[n_entries].task_id = task_id;
+ n_entries++;
+ if (n_entries == sizeof(entries)/sizeof(entries[0]))
+ break;
+ }
+ cmd_rx_bw_start(lcore_id);
+ cmd_tx_bw_start(lcore_id);
+ if (n_entries == sizeof(entries)/sizeof(entries[0]))
+ break;
+ }
+
+ struct header hdr;
+
+ header_init(&hdr, rte_get_tsc_hz(), rte_rdtsc(), n_entries);
+ header_add_field(&hdr, sizeof(((struct record *)0)->lcore_id));
+ header_add_field(&hdr, sizeof(((struct record *)0)->task_id));
+ header_add_field(&hdr, sizeof(((struct record *)0)->rx_bytes));
+ header_add_field(&hdr, sizeof(((struct record *)0)->tx_bytes));
+ header_add_field(&hdr, sizeof(((struct record *)0)->drop_bytes));
+ header_add_field(&hdr, sizeof(((struct record *)0)->tsc));
+ header_write(&hdr, fp);
+}
+
+void stats_cons_log_notify(void)
+{
+ for (uint32_t i = 0; i < n_entries; ++i) {
+ uint32_t c = entries[i].lcore_id;
+ uint32_t t = entries[i].task_id;
+ struct task_stats *l = stats_get_task_stats(c, t);
+ struct task_stats_sample *last = stats_get_task_stats_sample(c, t, 1);
+
+ buf[buf_pos].lcore_id = c;
+ buf[buf_pos].task_id = t;
+ buf[buf_pos].tx_bytes = last->tx_bytes;
+ buf[buf_pos].rx_bytes = last->rx_bytes;
+ buf[buf_pos].drop_bytes = last->drop_bytes;
+ /* buf[buf_pos].drop_tx_fail = l->tot_drop_tx_fail; */
+ buf[buf_pos].tsc = last->tsc;
+
+ buf_pos++;
+
+ if (buf_pos == sizeof(buf)/sizeof(buf[0])) {
+ fwrite(buf, sizeof(buf), 1, fp);
+ buf_pos = 0;
+ }
+ }
+}
+#endif
+
+void stats_cons_log_finish(void)
+{
+ if (fp) {
+ if (buf_pos) {
+ fwrite(buf, sizeof(buf[0]), buf_pos, fp);
+ buf_pos = 0;
+ }
+ fclose(fp);
+ }
+}