diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2022-04-14 18:12:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2022-04-14 18:12:14 +0000 |
commit | bb50acdcb8073654ea667b8c0272e335bd43f844 (patch) | |
tree | 1e00c8a29871426f8182658928dcb62e42d57ce8 /libnetdata/ebpf | |
parent | Releasing debian version 1.33.1-1. (diff) | |
download | netdata-bb50acdcb8073654ea667b8c0272e335bd43f844.tar.xz netdata-bb50acdcb8073654ea667b8c0272e335bd43f844.zip |
Merging upstream version 1.34.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libnetdata/ebpf')
-rw-r--r-- | libnetdata/ebpf/README.md | 2 | ||||
-rw-r--r-- | libnetdata/ebpf/ebpf.c | 268 | ||||
-rw-r--r-- | libnetdata/ebpf/ebpf.h | 45 |
3 files changed, 287 insertions, 28 deletions
diff --git a/libnetdata/ebpf/README.md b/libnetdata/ebpf/README.md index 09c6607d9..534867f31 100644 --- a/libnetdata/ebpf/README.md +++ b/libnetdata/ebpf/README.md @@ -2,4 +2,4 @@ custom_edit_url: https://github.com/netdata/netdata/edit/master/libnetdata/ebpf/README.md --> -[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Flibnetdata%2Febpf%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) + diff --git a/libnetdata/ebpf/ebpf.c b/libnetdata/ebpf/ebpf.c index ca40492f1..dde6d57fc 100644 --- a/libnetdata/ebpf/ebpf.c +++ b/libnetdata/ebpf/ebpf.c @@ -279,7 +279,7 @@ static char *ebpf_select_kernel_name(uint32_t selector) { static char *kernel_names[] = { NETDATA_IDX_STR_V3_10, NETDATA_IDX_STR_V4_14, NETDATA_IDX_STR_V4_16, NETDATA_IDX_STR_V4_18, NETDATA_IDX_STR_V5_4, NETDATA_IDX_STR_V5_10, - NETDATA_IDX_STR_V5_11, NETDATA_IDX_STR_V5_15 + NETDATA_IDX_STR_V5_11, NETDATA_IDX_STR_V5_15, NETDATA_IDX_STR_V5_16 }; return kernel_names[selector]; @@ -301,7 +301,9 @@ static int ebpf_select_max_index(int is_rhf, uint32_t kver) if (kver >= NETDATA_EBPF_KERNEL_4_11) return NETDATA_IDX_V4_18; } else { // Kernels from kernel.org - if (kver >= NETDATA_EBPF_KERNEL_5_15) + if (kver >= NETDATA_EBPF_KERNEL_5_16) + return NETDATA_IDX_V5_16; + else if (kver >= NETDATA_EBPF_KERNEL_5_15) return NETDATA_IDX_V5_15; else if (kver >= NETDATA_EBPF_KERNEL_5_11) return NETDATA_IDX_V5_11; @@ -451,14 +453,53 @@ void ebpf_update_pid_table(ebpf_local_maps_t *pid, ebpf_module_t *em) pid->user_input = em->pid_map_size; } -void ebpf_update_map_sizes(struct bpf_object *program, ebpf_module_t *em) +/** + * Update map size + * + * Update map size with information read from configuration files. + * + * @param map the structure with file descriptor to update. + * @param lmap the structure with information from configuration files. + * @param em the structure with information about how the module/thread is working. + * @param map_name the name of the file used to log. + */ +void ebpf_update_map_size(struct bpf_map *map, ebpf_local_maps_t *lmap, ebpf_module_t *em, const char *map_name) +{ + uint32_t apps_type = NETDATA_EBPF_MAP_PID | NETDATA_EBPF_MAP_RESIZABLE; + if (lmap->user_input && lmap->user_input != lmap->internal_input) { +#ifdef NETDATA_INTERNAL_CHECKS + info("Changing map %s from size %u to %u ", map_name, lmap->internal_input, lmap->user_input); +#endif +#ifdef LIBBPF_MAJOR_VERSION + bpf_map__set_max_entries(map, lmap->user_input); +#else + bpf_map__resize(map, lmap->user_input); +#endif + } else if (((lmap->type & apps_type) == apps_type) && (!em->apps_charts) && (!em->cgroup_charts)) { + lmap->user_input = ND_EBPF_DEFAULT_MIN_PID; +#ifdef LIBBPF_MAJOR_VERSION + bpf_map__set_max_entries(map, lmap->user_input); +#else + bpf_map__resize(map, lmap->user_input); +#endif + } +} + +/** + * Update Legacy map sizes + * + * Update map size for eBPF legacy code. + * + * @param program the structure with values read from binary. + * @param em the structure with information about how the module/thread is working. + */ +static void ebpf_update_legacy_map_sizes(struct bpf_object *program, ebpf_module_t *em) { struct bpf_map *map; ebpf_local_maps_t *maps = em->maps; if (!maps) return; - uint32_t apps_type = NETDATA_EBPF_MAP_PID | NETDATA_EBPF_MAP_RESIZABLE; bpf_map__for_each(map, program) { const char *map_name = bpf_map__name(map); @@ -467,15 +508,7 @@ void ebpf_update_map_sizes(struct bpf_object *program, ebpf_module_t *em) ebpf_local_maps_t *w = &maps[i]; if (w->type & NETDATA_EBPF_MAP_RESIZABLE) { if (!strcmp(w->name, map_name)) { - if (w->user_input && w->user_input != w->internal_input) { -#ifdef NETDATA_INTERNAL_CHECKS - info("Changing map %s from size %u to %u ", map_name, w->internal_input, w->user_input); -#endif - bpf_map__resize(map, w->user_input); - } else if (((w->type & apps_type) == apps_type) && (!em->apps_charts) && (!em->cgroup_charts)) { - w->user_input = ND_EBPF_DEFAULT_MIN_PID; - bpf_map__resize(map, w->user_input); - } + ebpf_update_map_size(map, w, em, map_name); } } @@ -564,7 +597,32 @@ static void ebpf_update_maps(ebpf_module_t *em, struct bpf_object *obj) } } -static void ebpf_update_controller(ebpf_module_t *em, struct bpf_object *obj) +/** + * Update Controller + * + * Update controller value with user input. + * + * @param fd the table file descriptor + * @param em structure with information about eBPF program we will load. + */ +void ebpf_update_controller(int fd, ebpf_module_t *em) +{ + uint32_t key = NETDATA_CONTROLLER_APPS_ENABLED; + uint32_t value = em->apps_charts | em->cgroup_charts; + int ret = bpf_map_update_elem(fd, &key, &value, 0); + if (ret) + error("Add key(%u) for controller table failed.", key); +} + +/** + * Update Legacy controller + * + * Update legacy controller table when eBPF program has it. + * + * @param em structure with information about eBPF program we will load. + * @param obj bpf object with tables. + */ +static void ebpf_update_legacy_controller(ebpf_module_t *em, struct bpf_object *obj) { ebpf_local_maps_t *maps = em->maps; if (!maps) @@ -580,11 +638,7 @@ static void ebpf_update_controller(ebpf_module_t *em, struct bpf_object *obj) w->type &= ~NETDATA_EBPF_MAP_CONTROLLER; w->type |= NETDATA_EBPF_MAP_CONTROLLER_UPDATED; - uint32_t key = NETDATA_CONTROLLER_APPS_ENABLED; - int value = em->apps_charts | em->cgroup_charts; - int ret = bpf_map_update_elem(w->map_fd, &key, &value, 0); - if (ret) - error("Add key(%u) for controller table failed.", key); + ebpf_update_controller(w->map_fd, em); } i++; } @@ -620,7 +674,7 @@ struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, int kv return NULL; } - ebpf_update_map_sizes(*obj, em); + ebpf_update_legacy_map_sizes(*obj, em); if (bpf_object__load(*obj)) { error("ERROR: loading BPF object file failed %s\n", lpath); @@ -629,7 +683,7 @@ struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, int kv } ebpf_update_maps(em, *obj); - ebpf_update_controller(em, *obj); + ebpf_update_legacy_controller(em, *obj); size_t count_programs = ebpf_count_programs(*obj); @@ -716,14 +770,131 @@ static void ebpf_select_mode_string(char *output, size_t len, netdata_run_mode_t } /** + * Convert string to load mode + * + * Convert the string given as argument to value present in enum. + * + * @param str value read from configuraion file. + * + * @return It returns the value to be used. + */ +netdata_ebpf_load_mode_t epbf_convert_string_to_load_mode(char *str) +{ + if (!strcasecmp(str, EBPF_CFG_CORE_PROGRAM)) + return EBPF_LOAD_CORE; + else if (!strcasecmp(str, EBPF_CFG_LEGACY_PROGRAM)) + return EBPF_LOAD_LEGACY; + + return EBPF_LOAD_PLAY_DICE; +} + +/** + * Convert load mode to string + * + * @param mode value that will select the string + * + * @return It returns the string associated to mode. + */ +static char *ebpf_convert_load_mode_to_string(netdata_ebpf_load_mode_t mode) +{ + if (mode == EBPF_LOAD_CORE) + return EBPF_CFG_CORE_PROGRAM; + else if (mode == EBPF_LOAD_LEGACY) + return EBPF_CFG_LEGACY_PROGRAM; + + return EBPF_CFG_DEFAULT_PROGRAM; +} + +/** + * CO-RE type + * + * Select the preferential type of CO-RE + * + * @param str value read from configuration file. + * @param lmode load mode used by collector. + */ +netdata_ebpf_program_loaded_t ebpf_convert_core_type(char *str, netdata_run_mode_t lmode) +{ + if (!strcasecmp(str, EBPF_CFG_ATTACH_TRACEPOINT)) + return EBPF_LOAD_TRACEPOINT; + else if (!strcasecmp(str, EBPF_CFG_ATTACH_PROBE)) { + return (lmode == MODE_ENTRY) ? EBPF_LOAD_PROBE : EBPF_LOAD_RETPROBE; + } + + return EBPF_LOAD_TRAMPOLINE; +} + +#ifdef LIBBPF_MAJOR_VERSION +/** + * Adjust Thread Load + * + * Adjust thread configuraton according specified load. + * + * @param mod the main structure that will be adjusted. + * @param file the btf file used with thread. + */ +void ebpf_adjust_thread_load(ebpf_module_t *mod, struct btf *file) +{ + if (!file) { + mod->load = EBPF_LOAD_LEGACY; + } else if (mod->load == EBPF_LOAD_PLAY_DICE && file) { + mod->load = EBPF_LOAD_CORE; + } +} + +/** + * + * @param filename + * @return + */ +struct btf *ebpf_parse_btf_file(const char *filename) +{ + struct btf *bf = btf__parse(filename, NULL); + if (libbpf_get_error(bf)) { + fprintf(stderr, "Cannot parse btf file"); + btf__free(bf); + return NULL; + } + + return bf; +} +#endif + +/** + * Update target with configuration + * + * Update target load mode with value. + * + * @param em the module structure + * @param value value used to update. + */ +static void ebpf_update_target_with_conf(ebpf_module_t *em, netdata_ebpf_program_loaded_t value) +{ + netdata_ebpf_targets_t *targets = em->targets; + if (!targets) { + return; + } + + int i = 0; + while (targets[i].name) { + targets[i].mode = value; + i++; + } +} + +/** + * Update Module using config + * + * Update configuration for a specific thread. + * * @param modules structure that will be updated */ void ebpf_update_module_using_config(ebpf_module_t *modules) { char default_value[EBPF_MAX_MODE_LENGTH + 1]; ebpf_select_mode_string(default_value, EBPF_MAX_MODE_LENGTH, modules->mode); - char *mode = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE, default_value); - modules->mode = ebpf_select_mode(mode); + char *value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE, default_value); + modules->mode = ebpf_select_mode(value); modules->update_every = (int)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_UPDATE_EVERY, modules->update_every); @@ -733,8 +904,15 @@ void ebpf_update_module_using_config(ebpf_module_t *modules) modules->pid_map_size = (uint32_t)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_PID_SIZE, modules->pid_map_size); -} + value = ebpf_convert_load_mode_to_string(modules->load); + value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, value); + modules->load = epbf_convert_string_to_load_mode(value); + + value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_CORE_ATTACH, EBPF_CFG_ATTACH_TRAMPOLINE); + netdata_ebpf_program_loaded_t fill_lm = ebpf_convert_core_type(value, modules->mode); + ebpf_update_target_with_conf(modules, fill_lm); +} /** * Update module @@ -991,3 +1169,45 @@ int ebpf_disable_tracing_values(char *subsys, char *eventname) { return ebpf_change_tracing_values(subsys, eventname, "0"); } + +/** + * Select PC prefix + * + * Identify the prefix to run on PC architecture. + * + * @return It returns 32 or 64 according to host arch. + */ +static uint32_t ebpf_select_pc_prefix() +{ + long counter = 1; + uint32_t i; + for (i = 0; i < 128; i++) { + counter <<= 1; + if (counter < 0) + break; + } + + return counter; +} + +/** + * Select Host Prefix + * + * Select prefix to syscall when host is running a kernel newer than 4.17.0 + * + * @param output the vector to store data. + * @param length length of output vector. + * @param syscall the syscall that prefix will be attached; + * @param kver the current kernel version in format MAJOR*65536 + MINOR*256 + PATCH + */ +void ebpf_select_host_prefix(char *output, size_t length, char *syscall, int kver) +{ + if (kver < NETDATA_EBPF_KERNEL_4_17) + snprintfz(output, length, "sys_%s", syscall); + else { + uint32_t arch = ebpf_select_pc_prefix(); + // Prefix selected according https://www.kernel.org/doc/html/latest/process/adding-syscalls.html + char *prefix = (arch == 32) ? "__ia32" : "__x64"; + snprintfz(output, length, "%s_sys_%s", prefix, syscall); + } +}
\ No newline at end of file diff --git a/libnetdata/ebpf/ebpf.h b/libnetdata/ebpf/ebpf.h index 125299672..f701e1d4d 100644 --- a/libnetdata/ebpf/ebpf.h +++ b/libnetdata/ebpf/ebpf.h @@ -5,6 +5,10 @@ #include <bpf/bpf.h> #include <bpf/libbpf.h> +#ifdef LIBBPF_DEPRECATED +#include <bpf/btf.h> +#include <linux/btf.h> +#endif #include <stdlib.h> // Necessary for stdtoul #define NETDATA_DEBUGFS "/sys/kernel/debug/tracing/" @@ -17,11 +21,25 @@ #define EBPF_CFG_LOAD_MODE_RETURN "return" #define EBPF_MAX_MODE_LENGTH 6 +#define EBPF_CFG_TYPE_FORMAT "ebpf type format" +#define EBPF_CFG_DEFAULT_PROGRAM "auto" +#define EBPF_CFG_CORE_PROGRAM "CO-RE" +#define EBPF_CFG_LEGACY_PROGRAM "legacy" + +#define EBPF_CFG_CORE_ATTACH "ebpf co-re tracing" +#define EBPF_CFG_ATTACH_TRAMPOLINE "trampoline" +#define EBPF_CFG_ATTACH_TRACEPOINT "tracepoint" +#define EBPF_CFG_ATTACH_PROBE "probe" + +#define EBPF_CFG_PROGRAM_PATH "btf path" + #define EBPF_CFG_UPDATE_EVERY "update every" #define EBPF_CFG_PID_SIZE "pid table size" #define EBPF_CFG_APPLICATION "apps" #define EBPF_CFG_CGROUP "cgroups" +#define EBPF_COMMON_FNCT_CLEAN_UP "release_task" + /** * The RedHat magic number was got doing: * @@ -57,7 +75,8 @@ enum netdata_ebpf_kernel_versions { NETDATA_EBPF_KERNEL_5_0 = 327680, // 327680 = 5 * 65536 + 0 * 256 NETDATA_EBPF_KERNEL_5_10 = 330240, // 330240 = 5 * 65536 + 10 * 256 NETDATA_EBPF_KERNEL_5_11 = 330496, // 330240 = 5 * 65536 + 11 * 256 - NETDATA_EBPF_KERNEL_5_15 = 331520 // 331520 = 5 * 65536 + 15 * 256 + NETDATA_EBPF_KERNEL_5_15 = 331520, // 331520 = 5 * 65536 + 15 * 256 + NETDATA_EBPF_KERNEL_5_16 = 331776 // 331776 = 5 * 65536 + 16 * 256 }; enum netdata_kernel_flag { @@ -68,7 +87,8 @@ enum netdata_kernel_flag { NETDATA_V5_4 = 1 << 4, NETDATA_V5_10 = 1 << 5, NETDATA_V5_11 = 1 << 6, - NETDATA_V5_15 = 1 << 7 + NETDATA_V5_15 = 1 << 7, + NETDATA_V5_16 = 1 << 8 }; enum netdata_kernel_idx { @@ -79,7 +99,8 @@ enum netdata_kernel_idx { NETDATA_IDX_V5_4 , NETDATA_IDX_V5_10, NETDATA_IDX_V5_11, - NETDATA_IDX_V5_15 + NETDATA_IDX_V5_15, + NETDATA_IDX_V5_16 }; #define NETDATA_IDX_STR_V3_10 "3.10" @@ -90,6 +111,7 @@ enum netdata_kernel_idx { #define NETDATA_IDX_STR_V5_10 "5.10" #define NETDATA_IDX_STR_V5_11 "5.11" #define NETDATA_IDX_STR_V5_15 "5.15" +#define NETDATA_IDX_STR_V5_16 "5.16" /** * Minimum value has relationship with libbpf support. @@ -229,6 +251,8 @@ extern void ebpf_load_addresses(ebpf_addresses_t *fa, int fd); extern void ebpf_fill_algorithms(int *algorithms, size_t length, int algorithm); extern char **ebpf_fill_histogram_dimension(size_t maximum); extern void ebpf_update_stats(ebpf_plugin_stats_t *report, ebpf_module_t *em); +extern void ebpf_update_controller(int fd, ebpf_module_t *em); +extern void ebpf_update_map_size(struct bpf_map *map, ebpf_local_maps_t *lmap, ebpf_module_t *em, const char *map_name); // Histogram #define NETDATA_EBPF_HIST_MAX_BINS 24UL @@ -250,4 +274,19 @@ extern int ebpf_is_tracepoint_enabled(char *subsys, char *eventname); extern int ebpf_enable_tracing_values(char *subsys, char *eventname); extern int ebpf_disable_tracing_values(char *subsys, char *eventname); +// BTF Section +#define EBPF_DEFAULT_BTF_FILE "/sys/kernel/btf" +#define EBPF_DEFAULT_ERROR_MSG "Cannot open or load BPF file for thread" + +// BTF helpers +#define NETDATA_EBPF_MAX_SYSCALL_LENGTH 255 + +extern netdata_ebpf_load_mode_t epbf_convert_string_to_load_mode(char *str); +extern netdata_ebpf_program_loaded_t ebpf_convert_core_type(char *str, netdata_run_mode_t lmode); +extern void ebpf_select_host_prefix(char *output, size_t length, char *syscall, int kver); +#ifdef LIBBPF_MAJOR_VERSION +extern void ebpf_adjust_thread_load(ebpf_module_t *mod, struct btf *file); +extern struct btf *ebpf_parse_btf_file(const char *filename); +#endif + #endif /* NETDATA_EBPF_H */ |