summaryrefslogtreecommitdiffstats
path: root/libnetdata/ebpf
diff options
context:
space:
mode:
Diffstat (limited to 'libnetdata/ebpf')
-rw-r--r--libnetdata/ebpf/ebpf.c121
-rw-r--r--libnetdata/ebpf/ebpf.h14
2 files changed, 118 insertions, 17 deletions
diff --git a/libnetdata/ebpf/ebpf.c b/libnetdata/ebpf/ebpf.c
index 61833dd7..b980d09e 100644
--- a/libnetdata/ebpf/ebpf.c
+++ b/libnetdata/ebpf/ebpf.c
@@ -453,6 +453,11 @@ void ebpf_update_stats(ebpf_plugin_stats_t *report, ebpf_module_t *em)
else if (em->load & EBPF_LOAD_CORE)
report->core++;
+ if (em->maps_per_core)
+ report->hash_percpu++;
+ else
+ report->hash_unique++;
+
ebpf_stats_targets(report, em->targets);
}
@@ -596,15 +601,70 @@ void ebpf_update_map_size(struct bpf_map *map, ebpf_local_maps_t *lmap, ebpf_mod
#endif
}
+#ifdef LIBBPF_MAJOR_VERSION
+/**
+ * Update map type
+ *
+ * Update map type with information given.
+ *
+ * @param map the map we want to modify
+ * @param w a structure with user input
+ */
+void ebpf_update_map_type(struct bpf_map *map, ebpf_local_maps_t *w)
+{
+ if (bpf_map__set_type(map, w->map_type)) {
+ error("Cannot modify map type for %s", w->name);
+ }
+}
+
+/**
+ * Define map type
+ *
+ * This PR defines the type used by hash tables according user input.
+ *
+ * @param maps the list of maps used with a hash table.
+ * @param maps_per_core define if map type according user specification.
+ * @param kver kernel version host is running.
+ */
+void ebpf_define_map_type(ebpf_local_maps_t *maps, int maps_per_core, int kver)
+{
+ if (!maps)
+ return;
+
+ // Before kernel 4.06 there was not percpu hash tables
+ if (kver < NETDATA_EBPF_KERNEL_4_06)
+ maps_per_core = CONFIG_BOOLEAN_NO;
+
+ int i = 0;
+ while (maps[i].name) {
+ ebpf_local_maps_t *map = &maps[i];
+ // maps_per_core is a boolean value in configuration files.
+ if (maps_per_core) {
+ if (map->map_type == BPF_MAP_TYPE_HASH)
+ map->map_type = BPF_MAP_TYPE_PERCPU_HASH;
+ else if (map->map_type == BPF_MAP_TYPE_ARRAY)
+ map->map_type = BPF_MAP_TYPE_PERCPU_ARRAY;
+ } else {
+ if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH)
+ map->map_type = BPF_MAP_TYPE_HASH;
+ else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
+ map->map_type = BPF_MAP_TYPE_ARRAY;
+ }
+
+ i++;
+ }
+}
+#endif
+
/**
- * Update Legacy map sizes
+ * Update Legacy map
*
- * Update map size for eBPF legacy code.
+ * Update map 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)
+static void ebpf_update_legacy_map(struct bpf_object *program, ebpf_module_t *em)
{
struct bpf_map *map;
ebpf_local_maps_t *maps = em->maps;
@@ -614,13 +674,19 @@ static void ebpf_update_legacy_map_sizes(struct bpf_object *program, ebpf_module
bpf_map__for_each(map, program)
{
const char *map_name = bpf_map__name(map);
- int i = 0; ;
+ int i = 0;
while (maps[i].name) {
ebpf_local_maps_t *w = &maps[i];
- if (w->type & NETDATA_EBPF_MAP_RESIZABLE) {
- if (!strcmp(w->name, map_name)) {
+
+ if (!strcmp(w->name, map_name)) {
+ // Modify size
+ if (w->type & NETDATA_EBPF_MAP_RESIZABLE) {
ebpf_update_map_size(map, w, em, map_name);
}
+
+#ifdef LIBBPF_MAJOR_VERSION
+ ebpf_update_map_type(map, w);
+#endif
}
i++;
@@ -790,13 +856,15 @@ struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, int kv
em->load |= EBPF_LOAD_LEGACY;
*obj = bpf_object__open_file(lpath, NULL);
+ if (!*obj)
+ return NULL;
+
if (libbpf_get_error(obj)) {
- error("Cannot open BPF object %s", lpath);
bpf_object__close(*obj);
return NULL;
}
- ebpf_update_legacy_map_sizes(*obj, em);
+ ebpf_update_legacy_map(*obj, em);
if (bpf_object__load(*obj)) {
error("ERROR: loading BPF object file failed %s\n", lpath);
@@ -1156,8 +1224,8 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_m
{
char default_value[EBPF_MAX_MODE_LENGTH + 1];
ebpf_select_mode_string(default_value, EBPF_MAX_MODE_LENGTH, modules->mode);
- char *value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE, default_value);
- modules->mode = ebpf_select_mode(value);
+ char *load_mode = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE, default_value);
+ modules->mode = ebpf_select_mode(load_mode);
modules->update_every = (int)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION,
EBPF_CFG_UPDATE_EVERY, modules->update_every);
@@ -1171,19 +1239,38 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_m
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 & NETDATA_EBPF_LOAD_METHODS);
- value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, value);
- netdata_ebpf_load_mode_t load = epbf_convert_string_to_load_mode(value);
+ char *value = ebpf_convert_load_mode_to_string(modules->load & NETDATA_EBPF_LOAD_METHODS);
+ char *type_format = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, value);
+ netdata_ebpf_load_mode_t load = epbf_convert_string_to_load_mode(type_format);
load = ebpf_select_load_mode(btf_file, load, kver, is_rh);
modules->load = origin | load;
- 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);
+ char *core_attach = 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(core_attach, modules->mode);
ebpf_update_target_with_conf(modules, fill_lm);
value = ebpf_convert_collect_pid_to_string(modules->apps_level);
- value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_COLLECT_PID, value);
- modules->apps_level = ebpf_convert_string_to_apps_level(value);
+ char *collect_pid = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_COLLECT_PID, value);
+ modules->apps_level = ebpf_convert_string_to_apps_level(collect_pid);
+
+ modules->maps_per_core = appconfig_get_boolean(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_MAPS_PER_CORE,
+ modules->maps_per_core);
+ if (kver < NETDATA_EBPF_KERNEL_4_06)
+ modules->maps_per_core = CONFIG_BOOLEAN_NO;
+
+#ifdef NETDATA_DEV_MODE
+ info("The thread %s was configured with: mode = %s; update every = %d; apps = %s; cgroup = %s; ebpf type format = %s; ebpf co-re tracing = %s; collect pid = %s; maps per core = %s",
+ modules->thread_name,
+ load_mode,
+ modules->update_every,
+ (modules->apps_charts)?"enabled":"disabled",
+ (modules->cgroup_charts)?"enabled":"disabled",
+ type_format,
+ core_attach,
+ collect_pid,
+ (modules->maps_per_core)?"enabled":"disabled"
+ );
+#endif
}
/**
diff --git a/libnetdata/ebpf/ebpf.h b/libnetdata/ebpf/ebpf.h
index bf5fdc33..e82aaedd 100644
--- a/libnetdata/ebpf/ebpf.h
+++ b/libnetdata/ebpf/ebpf.h
@@ -40,6 +40,8 @@
#define EBPF_CFG_PROGRAM_PATH "btf path"
+#define EBPF_CFG_MAPS_PER_CORE "maps per core"
+
#define EBPF_CFG_UPDATE_EVERY "update every"
#define EBPF_CFG_UPDATE_APPS_EVERY_DEFAULT 10
#define EBPF_CFG_PID_SIZE "pid table size"
@@ -77,6 +79,7 @@
*
*/
enum netdata_ebpf_kernel_versions {
+ NETDATA_EBPF_KERNEL_4_06 = 263680, // 264960 = 4 * 65536 + 6 * 256
NETDATA_EBPF_KERNEL_4_11 = 264960, // 264960 = 4 * 65536 + 15 * 256
NETDATA_EBPF_KERNEL_4_14 = 265728, // 264960 = 4 * 65536 + 14 * 256
NETDATA_EBPF_KERNEL_4_15 = 265984, // 265984 = 4 * 65536 + 15 * 256
@@ -196,6 +199,9 @@ typedef struct ebpf_local_maps {
uint32_t user_input;
uint32_t type;
int map_fd;
+#ifdef LIBBPF_MAJOR_VERSION
+ enum bpf_map_type map_type;
+#endif
} ebpf_local_maps_t;
typedef struct ebpf_specify_name {
@@ -243,6 +249,9 @@ typedef struct ebpf_plugin_stats {
uint64_t memlock_kern; // The same information reported by bpftool, but it is not accurated
// https://lore.kernel.org/linux-mm/20230112155326.26902-5-laoar.shao@gmail.com/T/
uint32_t hash_tables; // Number of hash tables used on the system.
+
+ uint32_t hash_percpu; // Number of threads running per cpu maps
+ uint32_t hash_unique; // Number of threads running an unique map for all cores.
} ebpf_plugin_stats_t;
typedef enum ebpf_stats_action {
@@ -296,6 +305,7 @@ typedef struct ebpf_module {
// charts
char memory_usage[NETDATA_EBPF_CHART_MEM_LENGTH];
char memory_allocations[NETDATA_EBPF_CHART_MEM_LENGTH];
+ int maps_per_core;
} ebpf_module_t;
int ebpf_get_kernel_version();
@@ -348,6 +358,7 @@ typedef struct ebpf_filesystem_partitions {
ebpf_addresses_t addresses;
uint64_t kernels;
+ ebpf_local_maps_t *fs_maps;
} ebpf_filesystem_partitions_t;
typedef struct ebpf_sync_syscalls {
@@ -365,6 +376,7 @@ typedef struct ebpf_sync_syscalls {
#else
void *sync_obj;
#endif
+ ebpf_local_maps_t *sync_maps;
} ebpf_sync_syscalls_t;
void ebpf_histogram_dimension_cleanup(char **ptr, size_t length);
@@ -391,6 +403,8 @@ void ebpf_adjust_thread_load(ebpf_module_t *mod, struct btf *file);
struct btf *ebpf_parse_btf_file(const char *filename);
struct btf *ebpf_load_btf_file(char *path, char *filename);
int ebpf_is_function_inside_btf(struct btf *file, char *function);
+void ebpf_update_map_type(struct bpf_map *map, ebpf_local_maps_t *w);
+void ebpf_define_map_type(ebpf_local_maps_t *maps, int maps_per_core, int kver);
#endif
void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report, ebpf_local_maps_t *maps);