summaryrefslogtreecommitdiffstats
path: root/libnetdata/ebpf/ebpf.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2021-05-19 12:33:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2021-05-19 12:33:59 +0000
commit1ee0c09c5742557e037df5421ca62abddb90ae22 (patch)
tree71c0fa48bb6d31d036c9badd7e038527f90d1a73 /libnetdata/ebpf/ebpf.c
parentReleasing debian version 1.30.1-1. (diff)
downloadnetdata-1ee0c09c5742557e037df5421ca62abddb90ae22.tar.xz
netdata-1ee0c09c5742557e037df5421ca62abddb90ae22.zip
Merging upstream version 1.31.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libnetdata/ebpf/ebpf.c')
-rw-r--r--libnetdata/ebpf/ebpf.c161
1 files changed, 144 insertions, 17 deletions
diff --git a/libnetdata/ebpf/ebpf.c b/libnetdata/ebpf/ebpf.c
index 8619ae26..1f71f6a2 100644
--- a/libnetdata/ebpf/ebpf.c
+++ b/libnetdata/ebpf/ebpf.c
@@ -295,25 +295,112 @@ static int select_file(char *name, const char *program, size_t length, int mode,
return ret;
}
-struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char *kernel_string, struct bpf_object **obj, int *map_fd)
+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)
+{
+ struct bpf_map *map;
+ ebpf_local_maps_t *maps = em->maps;
+ if (!maps)
+ return;
+
+ bpf_map__for_each(map, program)
+ {
+ const char *map_name = bpf_map__name(map);
+ int i = 0; ;
+ while (maps[i].name) {
+ ebpf_local_maps_t *w = &maps[i];
+ if (w->user_input != w->internal_input && !strcmp(w->name, map_name)) {
+#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);
+ }
+ i++;
+ }
+ }
+}
+
+size_t ebpf_count_programs(struct bpf_object *obj)
+{
+ size_t tot = 0;
+ struct bpf_program *prog;
+ bpf_object__for_each_program(prog, obj)
+ {
+ tot++;
+ }
+
+ return tot;
+}
+
+static ebpf_specify_name_t *ebpf_find_names(ebpf_specify_name_t *names, const char *prog_name)
+{
+ size_t i = 0;
+ while (names[i].program_name) {
+ if (!strcmp(prog_name, names[i].program_name))
+ return &names[i];
+
+ i++;
+ }
+
+ return NULL;
+}
+
+static struct bpf_link **ebpf_attach_programs(struct bpf_object *obj, size_t length, ebpf_specify_name_t *names)
+{
+ struct bpf_link **links = callocz(length , sizeof(struct bpf_link *));
+ size_t i = 0;
+ struct bpf_program *prog;
+ bpf_object__for_each_program(prog, obj)
+ {
+ links[i] = bpf_program__attach(prog);
+ if (libbpf_get_error(links[i]) && names) {
+ const char *name = bpf_program__name(prog);
+ ebpf_specify_name_t *w = ebpf_find_names(names, name);
+ if (w) {
+ enum bpf_prog_type type = bpf_program__get_type(prog);
+ if (type == BPF_PROG_TYPE_KPROBE)
+ links[i] = bpf_program__attach_kprobe(prog, w->retprobe, w->optional);
+ }
+ }
+
+ if (libbpf_get_error(links[i])) {
+ links[i] = NULL;
+ }
+
+ i++;
+ }
+
+ return links;
+}
+
+struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char *kernel_string,
+ struct bpf_object **obj, int *map_fd)
{
char lpath[4096];
char lname[128];
- int prog_fd;
int test = select_file(lname, em->thread_name, (size_t)127, em->mode, kernel_string);
if (test < 0 || test > 127)
return NULL;
snprintf(lpath, 4096, "%s/ebpf.d/%s", plugins_dir, lname);
- // We are using BPF_PROG_TYPE_UNSPEC instead a specific type for bpf_prog_load to define the type
- // according the eBPF program loaded
- if (bpf_prog_load(lpath, BPF_PROG_TYPE_UNSPEC, obj, &prog_fd)) {
- em->enabled = CONFIG_BOOLEAN_NO;
- info("Cannot load program: %s", lpath);
+ *obj = bpf_object__open_file(lpath, NULL);
+ if (libbpf_get_error(obj)) {
+ error("Cannot open BPF object %s", lpath);
+ bpf_object__close(*obj);
+ return NULL;
+ }
+
+ ebpf_update_map_sizes(*obj, em);
+
+ if (bpf_object__load(*obj)) {
+ error("ERROR: loading BPF object file failed %s\n", lpath);
+ bpf_object__close(*obj);
return NULL;
- } else {
- info("The eBPF program %s was loaded with success.", em->thread_name);
}
struct bpf_map *map;
@@ -324,16 +411,53 @@ struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char *
i++;
}
- struct bpf_program *prog;
- struct bpf_link **links = callocz(NETDATA_MAX_PROBES , sizeof(struct bpf_link *));
- i = 0;
- bpf_object__for_each_program(prog, *obj)
- {
- links[i] = bpf_program__attach(prog);
- i++;
+ size_t count_programs = ebpf_count_programs(*obj);
+
+ return ebpf_attach_programs(*obj, count_programs, em->names);
+}
+
+static char *ebpf_update_name(char *search)
+{
+ char filename[FILENAME_MAX + 1];
+ char *ret = NULL;
+ snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, NETDATA_KALLSYMS);
+ procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
+ if(unlikely(!ff)) {
+ error("Cannot open %s%s", netdata_configured_host_prefix, NETDATA_KALLSYMS);
+ return ret;
}
- return links;
+ ff = procfile_readall(ff);
+ if(unlikely(!ff))
+ return ret;
+
+ unsigned long i, lines = procfile_lines(ff);
+ size_t length = strlen(search);
+ for(i = 0; i < lines ; i++) {
+ char *cmp = procfile_lineword(ff, i,2);;
+ if (!strncmp(search, cmp, length)) {
+ ret = strdupz(cmp);
+ break;
+ }
+ }
+
+ procfile_close(ff);
+
+ return ret;
+}
+
+void ebpf_update_names(ebpf_specify_name_t *opt, ebpf_module_t *em)
+{
+ int mode = em->mode;
+ em->names = opt;
+
+ size_t i = 0;
+ while (opt[i].program_name) {
+ opt[i].retprobe = (mode == MODE_RETURN);
+ opt[i].optional = ebpf_update_name(opt[i].function_to_attach);
+
+ i++;
+ }
}
//----------------------------------------------------------------------------------------------------------------------
@@ -368,6 +492,9 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, struct config *cfg)
modules->apps_charts = appconfig_get_boolean(cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_APPLICATION,
CONFIG_BOOLEAN_YES);
+
+ modules->pid_map_size = (uint32_t)appconfig_get_number(cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_PID_SIZE,
+ modules->pid_map_size);
}