This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
stellar-stellar/src/core/stellar_stat.cpp

307 lines
17 KiB
C++
Raw Normal View History

2024-06-25 14:08:33 +08:00
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "log.h"
#include "stellar_stat.h"
#include "fieldstat/fieldstat_easy.h"
#include "fieldstat/fieldstat_exporter.h"
#define STAT_LOG_ERROR(format, ...) LOG_ERROR("stat", format, ##__VA_ARGS__)
#define IS_FREE 0
#define IS_BUSY 0xf
typedef uint64_t get_val_func(struct thread_stat *thr_stat);
static inline uint64_t get_dev_rx_pkts(struct thread_stat *thr_stat) { return thr_stat->packet_io->dev_rx_pkts; }
static inline uint64_t get_dev_rx_bytes(struct thread_stat *thr_stat) { return thr_stat->packet_io->dev_rx_bytes; }
static inline uint64_t get_dev_tx_pkts(struct thread_stat *thr_stat) { return thr_stat->packet_io->dev_tx_pkts; }
static inline uint64_t get_dev_tx_bytes(struct thread_stat *thr_stat) { return thr_stat->packet_io->dev_tx_bytes; }
static inline uint64_t get_keep_alive_pkts(struct thread_stat *thr_stat) { return thr_stat->packet_io->keep_alive_pkts; }
static inline uint64_t get_keep_alive_bytes(struct thread_stat *thr_stat) { return thr_stat->packet_io->keep_alive_bytes; }
static inline uint64_t get_raw_rx_pkts(struct thread_stat *thr_stat) { return thr_stat->packet_io->raw_rx_pkts; }
static inline uint64_t get_raw_rx_bytes(struct thread_stat *thr_stat) { return thr_stat->packet_io->raw_rx_bytes; }
static inline uint64_t get_raw_tx_pkts(struct thread_stat *thr_stat) { return thr_stat->packet_io->raw_tx_pkts; }
static inline uint64_t get_raw_tx_bytes(struct thread_stat *thr_stat) { return thr_stat->packet_io->raw_tx_bytes; }
static inline uint64_t get_drop_pkts(struct thread_stat *thr_stat) { return thr_stat->packet_io->drop_pkts; }
static inline uint64_t get_drop_bytes(struct thread_stat *thr_stat) { return thr_stat->packet_io->drop_bytes; }
static inline uint64_t get_inject_pkts(struct thread_stat *thr_stat) { return thr_stat->packet_io->inject_pkts; }
static inline uint64_t get_inject_bytes(struct thread_stat *thr_stat) { return thr_stat->packet_io->inject_bytes; }
static inline uint64_t get_ctrl_rx_pkts(struct thread_stat *thr_stat) { return thr_stat->packet_io->ctrl_rx_pkts; }
static inline uint64_t get_ctrl_rx_bytes(struct thread_stat *thr_stat) { return thr_stat->packet_io->ctrl_rx_bytes; }
static inline uint64_t get_ctrl_tx_pkts(struct thread_stat *thr_stat) { return thr_stat->packet_io->ctrl_tx_pkts; }
static inline uint64_t get_ctrl_tx_bytes(struct thread_stat *thr_stat) { return thr_stat->packet_io->ctrl_tx_bytes; }
static inline uint64_t get_ip4_flow_find(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_find; }
static inline uint64_t get_ip4_flow_add(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_add; }
static inline uint64_t get_ip4_flow_del(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_del; }
static inline uint64_t get_ip4_flow_timeout(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_timeout; }
static inline uint64_t get_ip4_flow_fail_no_space(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_fail_no_space; }
static inline uint64_t get_ip4_flow_fail_overlap(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_fail_overlap; }
static inline uint64_t get_ip4_flow_fail_many_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_fail_many_frag; }
static inline uint64_t get_ip4_flow_fail_invalid_length(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_fail_invalid_length; }
static inline uint64_t get_ip4_flow_bypass_dup_fist_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_bypass_dup_fist_frag; }
static inline uint64_t get_ip4_flow_bypass_dup_last_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_bypass_dup_last_frag; }
static inline uint64_t get_ip6_flow_find(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_find; }
static inline uint64_t get_ip6_flow_add(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_add; }
static inline uint64_t get_ip6_flow_del(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_del; }
static inline uint64_t get_ip6_flow_timeout(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_timeout; }
static inline uint64_t get_ip6_flow_fail_no_space(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_fail_no_space; }
static inline uint64_t get_ip6_flow_fail_overlap(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_fail_overlap; }
static inline uint64_t get_ip6_flow_fail_many_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_fail_many_frag; }
static inline uint64_t get_ip6_flow_fail_invalid_length(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_fail_invalid_length; }
static inline uint64_t get_ip6_flow_bypass_dup_fist_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_bypass_dup_fist_frag; }
static inline uint64_t get_ip6_flow_bypass_dup_last_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_bypass_dup_last_frag; }
static inline uint64_t get_total_tcp_sess_used(struct thread_stat *thr_stat) { return thr_stat->session_mgr->total_tcp_sess_used; }
static inline uint64_t get_curr_tcp_sess_used(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_used; }
static inline uint64_t get_curr_tcp_sess_opening(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_opening; }
static inline uint64_t get_curr_tcp_sess_active(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_active; }
static inline uint64_t get_curr_tcp_sess_closing(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_closing; }
static inline uint64_t get_curr_tcp_sess_discard(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_discard; }
static inline uint64_t get_curr_tcp_sess_closed(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_closed; }
static inline uint64_t get_total_udp_sess_used(struct thread_stat *thr_stat) { return thr_stat->session_mgr->total_udp_sess_used; }
static inline uint64_t get_curr_udp_sess_used(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_used; }
static inline uint64_t get_curr_udp_sess_opening(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_opening; }
static inline uint64_t get_curr_udp_sess_active(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_active; }
static inline uint64_t get_curr_udp_sess_closing(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_closing; }
static inline uint64_t get_curr_udp_sess_discard(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_discard; }
static inline uint64_t get_curr_udp_sess_closed(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_closed; }
static inline uint64_t get_tcp_sess_evicted(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_sess_evicted; }
static inline uint64_t get_udp_sess_evicted(struct thread_stat *thr_stat) { return thr_stat->session_mgr->udp_sess_evicted; }
static inline uint64_t get_udp_pkts_nospace_bypass(struct thread_stat *thr_stat) { return thr_stat->session_mgr->udp_pkts_nospace_bypass; }
static inline uint64_t get_tcp_pkts_nospace_bypass(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_pkts_nospace_bypass; }
static inline uint64_t get_tcp_pkts_nosess_bypass(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_pkts_nosess_bypass; }
static inline uint64_t get_tcp_pkts_duped_bypass(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_pkts_duped_bypass; }
static inline uint64_t get_udp_pkts_duped_bypass(struct thread_stat *thr_stat) { return thr_stat->session_mgr->udp_pkts_duped_bypass; }
static inline uint64_t get_udp_pkts_evctd_bypass(struct thread_stat *thr_stat) { return thr_stat->session_mgr->udp_pkts_evctd_bypass; }
static inline uint64_t get_tcp_seg_received(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_seg_received; }
static inline uint64_t get_tcp_seg_expired(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_seg_expired; }
static inline uint64_t get_tcp_seg_retransmit(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_seg_retransmit; }
static inline uint64_t get_tcp_seg_overlap(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_seg_overlap; }
static inline uint64_t get_tcp_seg_no_space(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_seg_no_space; }
static inline uint64_t get_tcp_seg_inorder(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_seg_inorder; }
static inline uint64_t get_tcp_seg_reorded(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_seg_reorded; }
static inline uint64_t get_tcp_seg_buffered(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_seg_buffered; }
static inline uint64_t get_tcp_seg_released(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_seg_released; }
2024-06-25 14:08:33 +08:00
struct metric_schema
{
const char *name;
get_val_func *get_val;
} schemas[] =
{
// device packet
{"dev_rx_pkts", get_dev_rx_pkts},
{"dev_rx_bytes", get_dev_rx_bytes},
{"dev_tx_pkts", get_dev_tx_pkts},
{"dev_tx_bytes", get_dev_tx_bytes},
// keep-alive packet
{"keep_alive_pkts", get_keep_alive_pkts},
{"keep_alive_bytes", get_keep_alive_bytes},
// raw packet
{"raw_rx_pkts", get_raw_rx_pkts},
{"raw_rx_bytes", get_raw_rx_bytes},
{"raw_tx_pkts", get_raw_tx_pkts},
{"raw_tx_bytes", get_raw_tx_bytes},
// drop packet
{"drop_pkts", get_drop_pkts},
{"drop_bytes", get_drop_bytes},
// inject packet
{"inject_pkts", get_inject_pkts},
{"inject_bytes", get_inject_bytes},
// ctrl packet
{"ctrl_rx_pkts", get_ctrl_rx_pkts},
{"ctrl_rx_bytes", get_ctrl_rx_bytes},
{"ctrl_tx_pkts", get_ctrl_tx_pkts},
{"ctrl_tx_bytes", get_ctrl_tx_bytes},
// ipv4 reassembly
{"ip4_flow_find", get_ip4_flow_find},
{"ip4_flow_add", get_ip4_flow_add},
{"ip4_flow_del", get_ip4_flow_del},
{"ip4_flow_timeout", get_ip4_flow_timeout},
{"ip4_flow_fail_no_space", get_ip4_flow_fail_no_space},
{"ip4_flow_fail_overlap", get_ip4_flow_fail_overlap},
{"ip4_flow_fail_many_frag", get_ip4_flow_fail_many_frag},
{"ip4_flow_fail_invalid_length", get_ip4_flow_fail_invalid_length},
{"ip4_flow_bypass_dup_fist_frag", get_ip4_flow_bypass_dup_fist_frag},
{"ip4_flow_bypass_dup_last_frag", get_ip4_flow_bypass_dup_last_frag},
// ipv6 reassembly
{"ip6_flow_find", get_ip6_flow_find},
{"ip6_flow_add", get_ip6_flow_add},
{"ip6_flow_del", get_ip6_flow_del},
{"ip6_flow_timeout", get_ip6_flow_timeout},
{"ip6_flow_fail_no_space", get_ip6_flow_fail_no_space},
{"ip6_flow_fail_overlap", get_ip6_flow_fail_overlap},
{"ip6_flow_fail_many_frag", get_ip6_flow_fail_many_frag},
{"ip6_flow_fail_invalid_length", get_ip6_flow_fail_invalid_length},
{"ip6_flow_bypass_dup_fist_frag", get_ip6_flow_bypass_dup_fist_frag},
{"ip6_flow_bypass_dup_last_frag", get_ip6_flow_bypass_dup_last_frag},
// TCP session
{"total_tcp_sess_used", get_total_tcp_sess_used},
{"curr_tcp_sess_used", get_curr_tcp_sess_used},
{"curr_tcp_sess_opening", get_curr_tcp_sess_opening},
{"curr_tcp_sess_active", get_curr_tcp_sess_active},
{"curr_tcp_sess_closing", get_curr_tcp_sess_closing},
{"curr_tcp_sess_discard", get_curr_tcp_sess_discard},
{"curr_tcp_sess_closed", get_curr_tcp_sess_closed},
2024-06-25 14:08:33 +08:00
// UDP session
{"total_udp_sess_used", get_total_udp_sess_used},
{"curr_udp_sess_used", get_curr_udp_sess_used},
{"curr_udp_sess_opening", get_curr_udp_sess_opening},
{"curr_udp_sess_active", get_curr_udp_sess_active},
{"curr_udp_sess_closing", get_curr_udp_sess_closing},
{"curr_udp_sess_discard", get_curr_udp_sess_discard},
{"curr_udp_sess_closed", get_curr_udp_sess_closed},
2024-06-25 14:08:33 +08:00
// Evicted session
{"tcp_sess_evicted", get_tcp_sess_evicted},
{"udp_sess_evicted", get_udp_sess_evicted},
2024-06-25 14:08:33 +08:00
// Packet
{"udp_pkts_nospace_bypass", get_udp_pkts_nospace_bypass},
{"tcp_pkts_nospace_bypass", get_tcp_pkts_nospace_bypass},
{"tcp_pkts_nosess_bypass", get_tcp_pkts_nosess_bypass},
{"tcp_pkts_duped_bypass", get_tcp_pkts_duped_bypass},
{"udp_pkts_duped_bypass", get_udp_pkts_duped_bypass},
{"udp_pkts_evctd_bypass", get_udp_pkts_evctd_bypass},
2024-06-25 14:08:33 +08:00
// TCP segments
{"tcp_seg_received", get_tcp_seg_received},
{"tcp_seg_expired", get_tcp_seg_expired},
{"tcp_seg_retransmit", get_tcp_seg_retransmit},
{"tcp_seg_overlap", get_tcp_seg_overlap},
{"tcp_seg_no_space", get_tcp_seg_no_space},
{"tcp_seg_inorder", get_tcp_seg_inorder},
{"tcp_seg_reorded", get_tcp_seg_reorded},
{"tcp_seg_buffered", get_tcp_seg_buffered},
{"tcp_seg_released", get_tcp_seg_released},
2024-06-25 14:08:33 +08:00
};
struct stellar_stat
{
uint16_t nr_thread;
char output_file[2048];
struct fieldstat_easy *fs;
int flag[MAX_THREAD_NUM]; // IS_FREE or IS_BUSY
struct thread_stat thr_stat[MAX_THREAD_NUM];
struct metric_map
{
uint64_t key;
uint64_t val;
} map[sizeof(schemas) / sizeof(struct metric_schema)];
};
// python3 -m pip install prettytable
// python3 -m pip install jinja2
// /opt/MESA/bin/fieldstat_exporter.py local -j log/stellar_fs4.json -e -l --clear-screen
struct stellar_stat *stellar_stat_new(uint16_t nr_thread)
{
char cwd[1024] = {0};
struct stellar_stat *stat = (struct stellar_stat *)calloc(1, sizeof(struct stellar_stat));
if (stat == NULL)
{
return NULL;
}
if (getcwd(cwd, sizeof(cwd)) == NULL)
{
STAT_LOG_ERROR("failed to get current working directory: %s", strerror(errno));
goto error_out;
}
snprintf(stat->output_file, sizeof(stat->output_file), "%s/log/stellar_fs4.json", cwd);
stat->fs = fieldstat_easy_new(1, "stellar", NULL, 0);
if (stat->fs == NULL)
{
STAT_LOG_ERROR("failed to create fieldstat_easy");
goto error_out;
}
stat->nr_thread = nr_thread;
for (int i = 0; i < MAX_THREAD_NUM; i++)
{
stat->flag[i] = IS_FREE;
}
for (size_t i = 0; i < sizeof(schemas) / sizeof(struct metric_schema); i++)
{
stat->map[i].key = fieldstat_easy_register_counter(stat->fs, schemas[i].name);
stat->map[i].val = 0;
}
return stat;
error_out:
stellar_stat_free(stat);
return NULL;
}
void stellar_stat_free(struct stellar_stat *stat)
{
if (stat)
{
if (stat->fs)
{
fieldstat_easy_free(stat->fs);
stat->fs = NULL;
}
free(stat);
stat = NULL;
}
}
void stellar_stat_output(struct stellar_stat *stat)
{
for (uint16_t i = 0; i < stat->nr_thread; i++)
{
if (ATOMIC_READ(&(stat->flag[i])) == IS_BUSY)
{
struct thread_stat *thr_stat = &stat->thr_stat[i];
for (size_t j = 0; j < sizeof(schemas) / sizeof(struct metric_schema); j++)
{
stat->map[j].val += schemas[j].get_val(thr_stat);
}
memset(thr_stat, 0, sizeof(struct thread_stat));
ATOMIC_SET(&(stat->flag[i]), IS_FREE);
}
}
for (size_t j = 0; j < sizeof(schemas) / sizeof(struct metric_schema); j++)
{
fieldstat_easy_counter_set(stat->fs, 0, stat->map[j].key, NULL, 0, stat->map[j].val);
}
char *buff;
size_t len;
fieldstat_easy_output(stat->fs, &buff, &len);
if (buff)
{
FILE *fp = fopen(stat->output_file, "w+");
if (fp == NULL)
{
STAT_LOG_ERROR("failed to open file: %s, %s", stat->output_file, strerror(errno));
}
else
{
fwrite(buff, len, 1, fp);
fflush(fp);
fclose(fp);
}
free(buff);
}
for (size_t j = 0; j < sizeof(schemas) / sizeof(struct metric_schema); j++)
{
stat->map[j].val = 0;
}
}
void stellar_stat_merge(struct stellar_stat *stat, const struct thread_stat *thr_stat, uint16_t thr_idx)
{
if (ATOMIC_READ(&(stat->flag[thr_idx])) == IS_FREE)
{
memcpy(&stat->thr_stat[thr_idx], thr_stat, sizeof(struct thread_stat));
ATOMIC_SET(&(stat->flag[thr_idx]), IS_BUSY);
}
}