// SPDX-License-Identifier: GPL-3.0-or-later
#include "ebpf.h"
#include "ebpf_swap.h"
static char *swap_dimension_name[NETDATA_SWAP_END] = { "read", "write" };
static netdata_syscall_stat_t swap_aggregated_data[NETDATA_SWAP_END];
static netdata_publish_syscall_t swap_publish_aggregated[NETDATA_SWAP_END];
static int read_thread_closed = 1;
netdata_publish_swap_t *swap_vector = NULL;
static netdata_idx_t swap_hash_values[NETDATA_SWAP_END];
static netdata_idx_t *swap_values = NULL;
netdata_publish_swap_t **swap_pid = NULL;
struct config swap_config = { .first_section = NULL,
.last_section = NULL,
.mutex = NETDATA_MUTEX_INITIALIZER,
.index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
.rwlock = AVL_LOCK_INITIALIZER } };
static ebpf_local_maps_t swap_maps[] = {{.name = "tbl_pid_swap", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
.user_input = 0,
.type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
{.name = "swap_ctrl", .internal_input = NETDATA_CONTROLLER_END,
.user_input = 0,
.type = NETDATA_EBPF_MAP_CONTROLLER,
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
{.name = "tbl_swap", .internal_input = NETDATA_SWAP_END,
.user_input = 0,
.type = NETDATA_EBPF_MAP_STATIC,
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
{.name = NULL, .internal_input = 0, .user_input = 0}};
static struct bpf_link **probe_links = NULL;
static struct bpf_object *objects = NULL;
struct netdata_static_thread swap_threads = {"SWAP KERNEL", NULL, NULL, 1,
NULL, NULL, NULL};
netdata_ebpf_targets_t swap_targets[] = { {.name = "swap_readpage", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = "swap_writepage", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
#ifdef LIBBPF_MAJOR_VERSION
#include "includes/swap.skel.h" // BTF code
static struct swap_bpf *bpf_obj = NULL;
/**
* Disable probe
*
* Disable all probes to use exclusively another method.
*
* @param obj is the main structure for bpf objects
*/
static void ebpf_swap_disable_probe(struct swap_bpf *obj)
{
bpf_program__set_autoload(obj->progs.netdata_swap_readpage_probe, false);
bpf_program__set_autoload(obj->progs.netdata_swap_writepage_probe, false);
}
/*
* Disable trampoline
*
* Disable all trampoline to use exclusively another method.
*
* @param obj is the main structure for bpf objects.
*/
static void ebpf_swap_disable_trampoline(struct swap_bpf *obj)
{
bpf_program__set_autoload(obj->progs.netdata_swap_readpage_fentry, false);
bpf_program__set_autoload(obj->progs.netdata_swap_writepage_fentry, false);
}
/**
* Set trampoline target
*
* Set the targets we will monitor.
*
* @param obj is the main structure for bpf objects.
*/
static void ebpf_swap_set_trampoline_target(struct swap_bpf *obj)
{
bpf_program__set_attach_target(obj->progs.netdata_swap_readpage_fentry, 0,
swap_targets[NETDATA_KEY_SWAP_READPAGE_CALL].name);
bpf_program__set_attach_target(obj->progs.netdata_swap_writepage_fentry, 0,
swap_targets[NETDATA_KEY_SWAP_WRITEPAGE_CALL].name);
}
/**
* Mount Attach Probe
*
* Attach probes to target
*
* @param obj is the main structure for bpf objects.
*
* @return It returns 0 on success and -1 otherwise.
*/
static int ebpf_swap_attach_kprobe(struct swap_bpf *obj)
{
obj->links.netdata_swap_readpage_probe = bpf_program__attach_kprobe(obj->progs.netdata_swap_readpage_probe,
false,
swap_targets[NETDATA_KEY_SWAP_READPAGE_CALL].name);
int ret = libbpf_get_error(obj->links.netdata_swap_readpage_probe);
if (ret)
return -1;
obj->links.netdata_swap_writepage_probe = bpf_program__attach_kprobe(obj->progs.netdata_swap_writepage_probe,
false,
swap_targets[NETDATA_KEY_SWAP_WRITEPAGE_CALL].name);
ret = libbpf_get_error(obj->links.netdata_swap_writepage_probe);
if (ret)
return -1;
return 0;
}
/**
* Set hash tables
*
* Set the values for maps according the value given by kernel.
*
* @param obj is the main structure for bpf objects.
*/
static void ebpf_swap_set_hash_tables(struct swap_bpf *obj)
{
swap_maps[NETDATA_PID_SWAP_TABLE].map_fd = bpf_map__fd(obj->maps.tbl_pid_swap);
swap_maps[NETDATA_SWAP_CONTROLLER].map_fd = bpf_map__fd(obj->maps.swap_ctrl);
swap_maps[NETDATA_SWAP_GLOBAL_TABLE].map