Add option to calculate packet counters per second.

This commit is contained in:
Christian Deacon
2025-02-26 18:53:14 -05:00
parent 03f67fb063
commit c567a028ed
6 changed files with 81 additions and 22 deletions

View File

@@ -128,6 +128,7 @@ The following table quickly explains the data types used within the configuratio
| interface | string | `NULL` | The network interface name to attach the XDP program to (usually retrieved with `ip a` or `ifconfig`). |
| update_time | uint | `0` | How often to update the config and filtering rules from the file system in seconds (0 disables). |
| no_stats | bool | `false` | Whether to enable or disable packet counters. Disabling packet counters will improve performance, but result in less visibility on what the XDP Firewall is doing. |
| stats_per_second | bool | `false` | If true, packet counters and stats are calculated per second. `stdout_update_time` must be 1000 or less for this to work properly. |
| stdout_update_time | uint | `1000` | How often to update `stdout` when displaying packet counters in milliseconds. |
| filters | Array of Filter Object(s) | `NULL` | An array of filters to use with the XDP Firewall. |

View File

@@ -196,7 +196,7 @@ int main(int argc, char *argv[])
struct stat conf_stat;
// Check if we're doing stats.
if (!cfg.nostats)
if (!cfg.no_stats)
{
doing_stats = 1;
}
@@ -213,7 +213,7 @@ int main(int argc, char *argv[])
}
// Check for auto-update.
if (cfg.updatetime > 0 && (cur_time - last_update_check) > cfg.updatetime)
if (cfg.update_time > 0 && (cur_time - last_update_check) > cfg.update_time)
{
// Check if config file have been modified
if (stat(cmd.cfgfile, &conf_stat) == 0 && conf_stat.st_mtime > last_config_check) {
@@ -234,7 +234,7 @@ int main(int argc, char *argv[])
last_config_check = time(NULL);
// Make sure we set doing stats if needed.
if (!cfg.nostats && !doing_stats)
if (!cfg.no_stats && !doing_stats)
{
doing_stats = 1;
}
@@ -245,9 +245,9 @@ int main(int argc, char *argv[])
}
// Calculate and display stats if enabled.
if (!cfg.nostats)
if (!cfg.no_stats)
{
if (CalculateStats(stats_map, cpus))
if (CalculateStats(stats_map, cpus, cfg.stats_per_second))
{
LogMsg(&cfg, 1, 0, "[WARNING] Failed to calculate packet stats. Stats map FD => %d...\n", stats_map);
}

View File

@@ -46,9 +46,10 @@ void SetCfgDefaults(config__t *cfg)
{
cfg->verbose = 2;
cfg->log_file = strdup("/var/log/xdpfw/xdpfw.log");
cfg->updatetime = 0;
cfg->update_time = 0;
cfg->interface = NULL;
cfg->nostats = 0;
cfg->no_stats = 0;
cfg->stats_per_second = 0;
cfg->stdout_update_time = 1000;
for (int i = 0; i < MAX_FILTERS; i++)
@@ -214,11 +215,11 @@ int ReadCfg(config__t *cfg)
cfg->interface = strdup(interface);
// Get auto update time.
int updatetime;
int update_time;
if (config_lookup_int(&conf, "update_time", &updatetime) == CONFIG_TRUE)
if (config_lookup_int(&conf, "update_time", &update_time) == CONFIG_TRUE)
{
cfg->updatetime = updatetime;
cfg->update_time = update_time;
}
// Get stdout update time.
@@ -230,11 +231,19 @@ int ReadCfg(config__t *cfg)
}
// Get no stats.
int nostats;
int no_stats;
if (config_lookup_bool(&conf, "no_stats", &nostats) == CONFIG_TRUE)
if (config_lookup_bool(&conf, "no_stats", &no_stats) == CONFIG_TRUE)
{
cfg->nostats = nostats;
cfg->no_stats = no_stats;
}
// Stats per second.
int stats_per_second;
if (config_lookup_bool(&conf, "stats_per_second", &stats_per_second) == CONFIG_TRUE)
{
cfg->stats_per_second = stats_per_second;
}
// Read filters in filters_map structure.
@@ -586,9 +595,9 @@ void PrintConfig(config__t* cfg)
fprintf(stdout, "Printing config...\n");
fprintf(stdout, "\tGeneral Settings\n");
fprintf(stdout, "\t\tInterface Name => %s\n", cfg->interface);
fprintf(stdout, "\t\tUpdate Time => %d\n", cfg->updatetime);
fprintf(stdout, "\t\tUpdate Time => %d\n", cfg->update_time);
fprintf(stdout, "\t\tStdout Update Time => %d\n", cfg->stdout_update_time);
fprintf(stdout, "\t\tNo Stats => %d\n\n", cfg->nostats);
fprintf(stdout, "\t\tNo Stats => %d\n\n", cfg->no_stats);
fprintf(stdout, "\tFilters\n");

View File

@@ -18,8 +18,9 @@ struct config
int verbose;
char *log_file;
char *interface;
u16 updatetime;
unsigned int nostats : 1;
u16 update_time;
unsigned int no_stats : 1;
unsigned int stats_per_second : 1;
int stdout_update_time;
filter_t filters[MAX_FILTERS];
} typedef config__t; // config_t is taken by libconfig -.-

View File

@@ -1,14 +1,21 @@
#include <loader/utils/stats.h>
struct timespec last_update_time = {0};
u64 last_allowed = 0;
u64 last_dropped = 0;
u64 last_passed = 0;
/**
* Calculates and displays packet counters/stats.
*
* @param stats_map The stats map BPF FD.
* @param cpus The amount of CPUs the host has.
* @param per_second Calculate packet counters per second (PPS).
*
* @return 0 on success or 1 on failure.
*/
int CalculateStats(int stats_map, int cpus)
int CalculateStats(int stats_map, int cpus, int per_second)
{
u32 key = 0;
@@ -40,10 +47,49 @@ int CalculateStats(int stats_map, int cpus)
dropped += stats[i].dropped;
passed += stats[i].passed;
}
u64 allowed_val = allowed, dropped_val = dropped, passed_val = passed;
if (per_second)
{
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); // Get precise time
double elapsed_time = (now.tv_sec - last_update_time.tv_sec) +
(now.tv_nsec - last_update_time.tv_nsec) / 1e9;
if (elapsed_time > 0)
{
allowed_val = (allowed - last_allowed) / elapsed_time;
dropped_val = (dropped - last_dropped) / elapsed_time;
passed_val = (passed - last_passed) / elapsed_time;
}
last_allowed = allowed;
last_dropped = dropped;
last_passed = passed;
last_update_time = now;
}
char allowed_str[12];
char dropped_str[12];
char passed_str[12];
if (per_second)
{
snprintf(allowed_str, sizeof(allowed_str), "%llu PPS", allowed_val);
snprintf(dropped_str, sizeof(dropped_str), "%llu PPS", dropped_val);
snprintf(passed_str, sizeof(passed_str), "%llu PPS", passed_val);
}
else
{
snprintf(allowed_str, sizeof(allowed_str), "%llu", allowed_val);
snprintf(dropped_str, sizeof(dropped_str), "%llu", dropped_val);
snprintf(passed_str, sizeof(passed_str), "%llu", passed_val);
}
printf("\r\033[1;32mAllowed:\033[0m %llu | ", allowed);
printf("\033[1;31mDropped:\033[0m %llu | ", dropped);
printf("\033[1;34mPassed:\033[0m %llu", passed);
printf("\r\033[1;32mAllowed:\033[0m %s | ", allowed_str);
printf("\033[1;31mDropped:\033[0m %s | ", dropped_str);
printf("\033[1;34mPassed:\033[0m %s", passed_str);
fflush(stdout);

View File

@@ -8,4 +8,6 @@
#include <loader/utils/config.h>
#include <loader/utils/helpers.h>
int CalculateStats(int stats_map, int cpus);
#include <time.h>
int CalculateStats(int stats_map, int cpus, int per_second);