Implement new logging system.
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include <loader/utils/cmdline.h>
|
||||
#include <loader/utils/config.h>
|
||||
#include <loader/utils/xdp.h>
|
||||
#include <loader/utils/logging.h>
|
||||
#include <loader/utils/stats.h>
|
||||
#include <loader/utils/helpers.h>
|
||||
|
||||
@@ -37,16 +38,6 @@ int main(int argc, char *argv[])
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Raise RLimit.
|
||||
struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
|
||||
|
||||
if (setrlimit(RLIMIT_MEMLOCK, &rl))
|
||||
{
|
||||
fprintf(stderr, "[ERROR] Failed to raise rlimit. Please make sure this program is ran as root!\n");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Initialize config.
|
||||
config__t cfg = {0};
|
||||
|
||||
@@ -68,54 +59,87 @@ int main(int argc, char *argv[])
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
LogMsg(&cfg, 2, 0, "Raising RLimit...");
|
||||
|
||||
// Raise RLimit.
|
||||
struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
|
||||
|
||||
if (setrlimit(RLIMIT_MEMLOCK, &rl))
|
||||
{
|
||||
LogMsg(&cfg, 0, 1, "[ERROR] Failed to raise rlimit. Please make sure this program is ran as root!\n");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
LogMsg(&cfg, 2, 0, "Retrieving interface index for '%s'...", cfg.interface);
|
||||
|
||||
// Get interface index.
|
||||
int ifidx = if_nametoindex(cfg.interface);
|
||||
|
||||
if (ifidx < 0)
|
||||
{
|
||||
fprintf(stderr, "[ERROR] Failed to retrieve index of network interface '%s'.\n", cfg.interface);
|
||||
LogMsg(&cfg, 0, 1, "[ERROR] Failed to retrieve index of network interface '%s'.\n", cfg.interface);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
LogMsg(&cfg, 2, 0, "Loading XDP/BPF program at '%s'...", XDP_OBJ_PATH);
|
||||
|
||||
// Load BPF object.
|
||||
struct xdp_program *prog = LoadBpfObj(XDP_OBJ_PATH);
|
||||
|
||||
if (prog == NULL)
|
||||
{
|
||||
fprintf(stderr, "[ERROR] Failed to load eBPF object file. Object path => %s.\n", XDP_OBJ_PATH);
|
||||
LogMsg(&cfg, 0, 1, "[ERROR] Failed to load eBPF object file. Object path => %s.\n", XDP_OBJ_PATH);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
LogMsg(&cfg, 2, 0, "Attaching XDP program to interface '%s'...", cfg.interface);
|
||||
|
||||
// Attach XDP program.
|
||||
if ((ret = AttachXdp(prog, ifidx, 0, &cmd)) != 0)
|
||||
char *mode_used = NULL;
|
||||
|
||||
if ((ret = AttachXdp(prog, &mode_used, ifidx, 0, &cmd)) != 0)
|
||||
{
|
||||
fprintf(stderr, "[ERROR] Failed to attach XDP program to interface '%s' (%d).\n", cfg.interface, ret);
|
||||
LogMsg(&cfg, 0, 1, "[ERROR] Failed to attach XDP program to interface '%s' using available modes (%d).\n", cfg.interface, ret);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (mode_used != NULL)
|
||||
{
|
||||
LogMsg(&cfg, 1, 0, "Attached XDP program using mode '%s'...", mode_used);
|
||||
}
|
||||
|
||||
LogMsg(&cfg, 2, 0, "Retrieving BPF map FDs...");
|
||||
|
||||
// Retrieve BPF maps.
|
||||
int filters_map = FindMapFd(prog, "filters_map");
|
||||
|
||||
// Check for valid maps.
|
||||
if (filters_map < 0)
|
||||
{
|
||||
fprintf(stderr, "[ERROR] Failed to find 'filters_map' BPF map.\n");
|
||||
LogMsg(&cfg, 0, 1, "[ERROR] Failed to find 'filters_map' BPF map.\n");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
LogMsg(&cfg, 3, 0, "filters_map FD => %d.", filters_map);
|
||||
|
||||
int stats_map = FindMapFd(prog, "stats_map");
|
||||
|
||||
if (stats_map < 0)
|
||||
{
|
||||
fprintf(stderr, "[ERROR] Failed to find 'stats_map' BPF map.\n");
|
||||
LogMsg(&cfg, 0, 1, "[ERROR] Failed to find 'stats_map' BPF map.\n");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
LogMsg(&cfg, 3, 0, "stats_map FD => %d.", stats_map);
|
||||
|
||||
LogMsg(&cfg, 2, 0, "Updating filters...");
|
||||
|
||||
// Update BPF maps.
|
||||
UpdateFilters(filters_map, &cfg);
|
||||
|
||||
@@ -126,6 +150,8 @@ int main(int argc, char *argv[])
|
||||
// Receive CPU count for stats map parsing.
|
||||
int cpus = get_nprocs_conf();
|
||||
|
||||
LogMsg(&cfg, 4, 0, "Retrieved %d CPUs on host.", cpus);
|
||||
|
||||
unsigned int end_time = (cmd.time > 0) ? time(NULL) + cmd.time : 0;
|
||||
|
||||
// Create last updated variables.
|
||||
@@ -159,7 +185,7 @@ int main(int argc, char *argv[])
|
||||
// Update config.
|
||||
if ((ret = LoadConfig(&cfg, cmd.cfgfile)) != 0)
|
||||
{
|
||||
fprintf(stderr, "[WARNING] Failed to load config after update check (%d)...\n", ret);
|
||||
LogMsg(&cfg, 1, 0, "[WARNING] Failed to load config after update check (%d)...\n", ret);
|
||||
}
|
||||
|
||||
// Update BPF maps.
|
||||
@@ -178,7 +204,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
if (CalculateStats(stats_map, cpus))
|
||||
{
|
||||
fprintf(stderr, "[WARNING] Failed to calculate packet stats. Stats map FD => %d...\n", stats_map);
|
||||
LogMsg(&cfg, 1, 0, "[WARNING] Failed to calculate packet stats. Stats map FD => %d...\n", stats_map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,14 +214,14 @@ int main(int argc, char *argv[])
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
// Detach XDP program.
|
||||
if (AttachXdp(prog, ifidx, 1, &cmd))
|
||||
if (AttachXdp(prog, &mode_used, ifidx, 1, &cmd))
|
||||
{
|
||||
fprintf(stderr, "[ERROR] Failed to detach XDP program from interface '%s'.\n", cfg.interface);
|
||||
LogMsg(&cfg, 0, 1, "[ERROR] Failed to detach XDP program from interface '%s'.\n", cfg.interface);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fprintf(stdout, "Cleaned up and exiting...\n");
|
||||
LogMsg(&cfg, 1, 0, "Cleaned up and exiting...\n");
|
||||
|
||||
// Exit program successfully.
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
@@ -46,6 +46,8 @@ int LoadConfig(config__t *cfg, char *cfg_file)
|
||||
*/
|
||||
void SetCfgDefaults(config__t *cfg)
|
||||
{
|
||||
cfg->verbose = 1;
|
||||
cfg->log_file = strdup("/var/log/xdpfw/xdpfw.log");
|
||||
cfg->updatetime = 0;
|
||||
cfg->interface = NULL;
|
||||
cfg->nostats = 0;
|
||||
@@ -168,6 +170,35 @@ int ReadCfg(config__t *cfg)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int verbose;
|
||||
|
||||
if (config_lookup_int(&conf, "verbose", &verbose) == CONFIG_TRUE)
|
||||
{
|
||||
cfg->verbose = verbose;
|
||||
}
|
||||
|
||||
const char* log_file;
|
||||
|
||||
if (config_lookup_string(&conf, "log_file", &log_file) == CONFIG_TRUE)
|
||||
{
|
||||
// We must free previous value to prevent memory leak.
|
||||
if (cfg->log_file != NULL)
|
||||
{
|
||||
free(cfg->log_file);
|
||||
cfg->log_file = NULL;
|
||||
}
|
||||
|
||||
if (strlen(log_file) > 0)
|
||||
{
|
||||
cfg->log_file = strdup(log_file);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
cfg->log_file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Get interface.
|
||||
const char *interface;
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
struct config
|
||||
{
|
||||
int verbose;
|
||||
char *log_file;
|
||||
char *interface;
|
||||
u16 updatetime;
|
||||
unsigned int nostats : 1;
|
||||
|
||||
96
src/loader/utils/logging.c
Normal file
96
src/loader/utils/logging.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <loader/utils/logging.h>
|
||||
|
||||
/**
|
||||
* Prints a log message to stdout/stderr along with a file if specified.
|
||||
*
|
||||
* @param req_lvl The required level for this message.
|
||||
* @param cur_lvl The current verbose level.
|
||||
* @param error If 1, sets pipe to stderr instead of stdout.
|
||||
* @param msg The log message.
|
||||
* @param args A VA list of arguments for the message.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void LogMsgRaw(int req_lvl, int cur_lvl, int error, const char* log_path, const char* msg, va_list args)
|
||||
{
|
||||
if (cur_lvl < req_lvl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FILE* pipe = stdout;
|
||||
|
||||
if (error)
|
||||
{
|
||||
pipe = stderr;
|
||||
}
|
||||
|
||||
// We need to format the message.
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
int len = vsnprintf(NULL, 0, msg, args_copy);
|
||||
va_end(args_copy);
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char f_msg[len + 1];
|
||||
vsnprintf(f_msg, sizeof(f_msg), msg, args);
|
||||
|
||||
char full_msg[len + 6 + 1];
|
||||
snprintf(full_msg, sizeof(full_msg), "[%d] %s", req_lvl, f_msg);
|
||||
|
||||
fprintf(pipe, "%s\n", full_msg);
|
||||
|
||||
if (log_path != NULL)
|
||||
{
|
||||
FILE* log_file = fopen(log_path, "a");
|
||||
|
||||
if (!log_file)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
time_t now = time(NULL);
|
||||
struct tm* tm_val = localtime(&now);
|
||||
|
||||
if (!tm_val)
|
||||
{
|
||||
fclose(log_file);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
char log_file_msg[len + 22 + 1];
|
||||
|
||||
snprintf(log_file_msg, sizeof(log_file_msg), "[%02d-%02d-%02d %02d:%02d:%02d]%s", tm_val->tm_year % 100, tm_val->tm_mon + 1, tm_val->tm_mday,
|
||||
tm_val->tm_hour, tm_val->tm_min, tm_val->tm_sec, full_msg);
|
||||
|
||||
fprintf(log_file, "%s\n", log_file_msg);
|
||||
|
||||
fclose(log_file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a log message using LogMsgRaw().
|
||||
*
|
||||
* @param cfg A pointer to the config structure.
|
||||
* @param req_lvl The required level for this message.
|
||||
* @param error Whether this is an error.
|
||||
* @param msg The log message with format support.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void LogMsg(config__t* cfg, int req_lvl, int error, const char* msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
|
||||
LogMsgRaw(req_lvl, cfg->verbose, error, (const char*)cfg->log_file, msg, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
15
src/loader/utils/logging.h
Normal file
15
src/loader/utils/logging.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <common/all.h>
|
||||
|
||||
#include <loader/utils/config.h>
|
||||
|
||||
#include <xdp/libxdp.h>
|
||||
|
||||
void LogMsg(config__t* cfg, int req_lvl, int error, const char* msg, ...);
|
||||
@@ -60,31 +60,32 @@ struct xdp_program *LoadBpfObj(const char *file_name)
|
||||
* Attempts to attach or detach (progfd = -1) a BPF/XDP program to an interface.
|
||||
*
|
||||
* @param prog A pointer to the XDP program structure.
|
||||
* @param mode_used The mode being used.
|
||||
* @param ifidx The index to the interface to attach to.
|
||||
* @param detach If above 0, attempts to detach XDP program.
|
||||
* @param cmd A pointer to a cmdline struct that includes command line arguments (mostly checking for offload/HW mode set).
|
||||
*
|
||||
* @return 0 on success and 1 on error.
|
||||
*/
|
||||
int AttachXdp(struct xdp_program *prog, int ifidx, u8 detach, cmdline_t *cmd)
|
||||
int AttachXdp(struct xdp_program *prog, char** mode, int ifidx, u8 detach, cmdline_t *cmd)
|
||||
{
|
||||
int err;
|
||||
|
||||
u32 mode = XDP_MODE_NATIVE;
|
||||
char *smode;
|
||||
u32 attach_mode = XDP_MODE_NATIVE;
|
||||
|
||||
smode = "DRV/native";
|
||||
*mode = "DRV/native";
|
||||
|
||||
if (cmd->offload)
|
||||
{
|
||||
smode = "HW/offload";
|
||||
*mode = "HW/offload";
|
||||
|
||||
mode = XDP_MODE_HW;
|
||||
attach_mode = XDP_MODE_HW;
|
||||
}
|
||||
else if (cmd->skb)
|
||||
{
|
||||
smode = "SKB/generic";
|
||||
mode = XDP_MODE_SKB;
|
||||
*mode = "SKB/generic";
|
||||
|
||||
attach_mode = XDP_MODE_SKB;
|
||||
}
|
||||
|
||||
int exit = 0;
|
||||
@@ -96,39 +97,35 @@ int AttachXdp(struct xdp_program *prog, int ifidx, u8 detach, cmdline_t *cmd)
|
||||
|
||||
if (detach)
|
||||
{
|
||||
err = xdp_program__detach(prog, ifidx, mode, 0);
|
||||
err = xdp_program__detach(prog, ifidx, attach_mode, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = xdp_program__attach(prog, ifidx, mode, 0);
|
||||
err = xdp_program__attach(prog, ifidx, attach_mode, 0);
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
fprintf(stderr, "Could not attach with mode %s (%s) (%d).\n", smode, strerror(-err), -err);
|
||||
}
|
||||
|
||||
// Decrease mode.
|
||||
switch (mode)
|
||||
switch (attach_mode)
|
||||
{
|
||||
case XDP_MODE_HW:
|
||||
mode = XDP_MODE_NATIVE;
|
||||
smode = "DRV/native";
|
||||
attach_mode = XDP_MODE_NATIVE;
|
||||
*mode = "DRV/native";
|
||||
|
||||
break;
|
||||
|
||||
case XDP_MODE_NATIVE:
|
||||
mode = XDP_MODE_SKB;
|
||||
smode = "SKB/generic";
|
||||
attach_mode = XDP_MODE_SKB;
|
||||
*mode = "SKB/generic";
|
||||
|
||||
break;
|
||||
|
||||
case XDP_MODE_SKB:
|
||||
// Exit loop.
|
||||
exit = 1;
|
||||
smode = NULL;
|
||||
|
||||
*mode = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -142,16 +139,11 @@ int AttachXdp(struct xdp_program *prog, int ifidx, u8 detach, cmdline_t *cmd)
|
||||
}
|
||||
|
||||
// If exit is set to 1 or smode is NULL, it indicates full failure.
|
||||
if (exit || smode == NULL)
|
||||
if (exit || *mode == NULL)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (detach < 1)
|
||||
{
|
||||
fprintf(stdout, "Loaded XDP program on mode %s...\n", smode);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
|
||||
int FindMapFd(struct xdp_program *prog, const char *map_name);
|
||||
struct xdp_program *LoadBpfObj(const char *file_name);
|
||||
int AttachXdp(struct xdp_program *prog, int ifidx, u8 detach, cmdline_t *cmd);
|
||||
int AttachXdp(struct xdp_program *prog, char** mode, int ifidx, u8 detach, cmdline_t *cmd);
|
||||
void UpdateFilters(int filters_map, config__t *cfg);
|
||||
Reference in New Issue
Block a user