diff options
Diffstat (limited to '')
-rw-r--r-- | libnetdata/config/appconfig.c | 26 | ||||
-rw-r--r-- | libnetdata/config/appconfig.h | 1 | ||||
-rw-r--r-- | libnetdata/ebpf/ebpf.c | 392 | ||||
-rw-r--r-- | libnetdata/ebpf/ebpf.h | 76 | ||||
-rw-r--r-- | libnetdata/json/jsmn.c | 2 | ||||
-rw-r--r-- | libnetdata/libnetdata.h | 7 | ||||
-rw-r--r-- | libnetdata/log/log.h | 2 | ||||
-rw-r--r-- | libnetdata/procfile/procfile.c | 4 | ||||
-rw-r--r-- | libnetdata/socket/security.c | 1 | ||||
-rw-r--r-- | libnetdata/storage_number/storage_number.c | 18 | ||||
-rw-r--r-- | libnetdata/storage_number/storage_number.h | 17 | ||||
-rw-r--r-- | libnetdata/storage_number/tests/test_storage_number.c | 2 |
12 files changed, 485 insertions, 63 deletions
diff --git a/libnetdata/config/appconfig.c b/libnetdata/config/appconfig.c index 6e4df2d09..37e9e7688 100644 --- a/libnetdata/config/appconfig.c +++ b/libnetdata/config/appconfig.c @@ -225,6 +225,31 @@ void appconfig_section_destroy_non_loaded(struct config *root, const char *secti error("Cannot remove section '%s' from config.", section); return; } + + appconfig_wrlock(root); + + if (root->first_section == co) { + root->first_section = co->next; + + if (root->last_section == co) + root->last_section = root->first_section; + } else { + struct section *co_cur = root->first_section, *co_prev = NULL; + + while(co_cur && co_cur != co) { + co_prev = co_cur; + co_cur = co_cur->next; + } + + if (co_cur) { + co_prev->next = co_cur->next; + + if (root->last_section == co_cur) + root->last_section = co_prev; + } + } + + appconfig_unlock(root); avl_destroy_lock(&co->values_index); freez(co->name); @@ -771,6 +796,7 @@ void appconfig_generate(struct config *root, BUFFER *wb, int only_changed) || !strcmp(co->name, CONFIG_SECTION_BACKEND) || !strcmp(co->name, CONFIG_SECTION_STREAM) || !strcmp(co->name, CONFIG_SECTION_HOST_LABEL) + || !strcmp(co->name, CONFIG_SECTION_ML) ) pri = 0; else if(!strncmp(co->name, "plugin:", 7)) pri = 1; diff --git a/libnetdata/config/appconfig.h b/libnetdata/config/appconfig.h index 246d1d5b9..bfc927353 100644 --- a/libnetdata/config/appconfig.h +++ b/libnetdata/config/appconfig.h @@ -91,6 +91,7 @@ #define CONFIG_SECTION_HEALTH "health" #define CONFIG_SECTION_BACKEND "backend" #define CONFIG_SECTION_STREAM "stream" +#define CONFIG_SECTION_ML "ml" #define CONFIG_SECTION_EXPORTING "exporting:global" #define CONFIG_SECTION_PROMETHEUS "prometheus:exporter" #define CONFIG_SECTION_HOST_LABEL "host labels" diff --git a/libnetdata/ebpf/ebpf.c b/libnetdata/ebpf/ebpf.c index 1f71f6a24..1ccaa7b41 100644 --- a/libnetdata/ebpf/ebpf.c +++ b/libnetdata/ebpf/ebpf.c @@ -64,13 +64,19 @@ int clean_kprobe_events(FILE *out, int pid, netdata_ebpf_events_t *ptr) //---------------------------------------------------------------------------------------------------------------------- -int get_kernel_version(char *out, int size) +/** + * Get Kernel version + * + * Get the current kernel from /proc and returns an integer value representing it + * + * @return it returns a value representing the kernel version. + */ +int ebpf_get_kernel_version() { char major[16], minor[16], patch[16]; char ver[VERSION_STRING_LEN]; char *version = ver; - out[0] = '\0'; int fd = open("/proc/sys/kernel/osrelease", O_RDONLY); if (fd < 0) return -1; @@ -104,10 +110,6 @@ int get_kernel_version(char *out, int size) *move++ = *version++; *move = '\0'; - fd = snprintf(out, (size_t)size, "%s.%s.%s", major, minor, patch); - if (fd > size) - error("The buffer to store kernel version is not smaller than necessary."); - return ((int)(str2l(major) * 65536) + (int)(str2l(minor) * 256) + (int)str2l(patch)); } @@ -272,14 +274,24 @@ char *ebpf_kernel_suffix(int version, int isrh) //---------------------------------------------------------------------------------------------------------------------- -int ebpf_update_kernel(ebpf_data_t *ed) +/** + * Update Kernel + * + * Update string used to load eBPF programs + * + * @param ks vector to store the value + * @param length available length to store kernel + * @param isrh Is a Red Hat distribution? + * @param version the kernel version + */ +void ebpf_update_kernel(char *ks, size_t length, int isrh, int version) { - char *kernel = ebpf_kernel_suffix(ed->running_on_kernel, (ed->isrh < 0) ? 0 : 1); - size_t length = strlen(kernel); - strncpyz(ed->kernel_string, kernel, length); - ed->kernel_string[length] = '\0'; - - return 0; + char *kernel = ebpf_kernel_suffix(version, (isrh < 0) ? 0 : 1); + size_t len = strlen(kernel); + if (len > length) + len = length - 1; + strncpyz(ks, kernel, len); + ks[len] = '\0'; } static int select_file(char *name, const char *program, size_t length, int mode, char *kernel_string) @@ -307,18 +319,27 @@ void ebpf_update_map_sizes(struct bpf_object *program, ebpf_module_t *em) 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); 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)) { + 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); + 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); + 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); + } + } } + i++; } } @@ -377,8 +398,59 @@ static struct bpf_link **ebpf_attach_programs(struct bpf_object *obj, size_t len return links; } +static void ebpf_update_maps(ebpf_module_t *em, struct bpf_object *obj) +{ + if (!em->maps) + return; + + ebpf_local_maps_t *maps = em->maps; + struct bpf_map *map; + bpf_map__for_each(map, obj) + { + int fd = bpf_map__fd(map); + if (maps) { + const char *map_name = bpf_map__name(map); + int j = 0; ; + while (maps[j].name) { + ebpf_local_maps_t *w = &maps[j]; + if (w->map_fd == ND_EBPF_MAP_FD_NOT_INITIALIZED && !strcmp(map_name, w->name)) + w->map_fd = fd; + + j++; + } + } + } +} + +static void ebpf_update_controller(ebpf_module_t *em, struct bpf_object *obj) +{ + ebpf_local_maps_t *maps = em->maps; + if (!maps) + return; + + struct bpf_map *map; + bpf_map__for_each(map, obj) + { + size_t i = 0; + while (maps[i].name) { + ebpf_local_maps_t *w = &maps[i]; + if (w->map_fd != ND_EBPF_MAP_FD_NOT_INITIALIZED && (w->type & NETDATA_EBPF_MAP_CONTROLLER)) { + 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); + } + i++; + } + } +} + struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char *kernel_string, - struct bpf_object **obj, int *map_fd) + struct bpf_object **obj) { char lpath[4096]; char lname[128]; @@ -403,13 +475,8 @@ struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char * return NULL; } - struct bpf_map *map; - size_t i = 0; - bpf_map__for_each(map, *obj) - { - map_fd[i] = bpf_map__fd(map); - i++; - } + ebpf_update_maps(em, *obj); + ebpf_update_controller(em, *obj); size_t count_programs = ebpf_count_programs(*obj); @@ -462,7 +529,7 @@ void ebpf_update_names(ebpf_specify_name_t *opt, ebpf_module_t *em) //---------------------------------------------------------------------------------------------------------------------- -void ebpf_mount_config_name(char *filename, size_t length, char *path, char *config) +void ebpf_mount_config_name(char *filename, size_t length, char *path, const char *config) { snprintf(filename, length, "%s/ebpf.d/%s", path, config); } @@ -475,7 +542,7 @@ int ebpf_load_config(struct config *config, char *filename) static netdata_run_mode_t ebpf_select_mode(char *mode) { - if (!strcasecmp(mode, "return")) + if (!strcasecmp(mode,EBPF_CFG_LOAD_MODE_RETURN )) return MODE_RETURN; else if (!strcasecmp(mode, "dev")) return MODE_DEVMODE; @@ -483,17 +550,31 @@ static netdata_run_mode_t ebpf_select_mode(char *mode) return MODE_ENTRY; } -void ebpf_update_module_using_config(ebpf_module_t *modules, struct config *cfg) +static void ebpf_select_mode_string(char *output, size_t len, netdata_run_mode_t sel) { - char *mode = appconfig_get(cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE, EBPF_CFG_LOAD_MODE_DEFAULT); + if (sel == MODE_RETURN) + strncpyz(output, EBPF_CFG_LOAD_MODE_RETURN, len); + else + strncpyz(output, EBPF_CFG_LOAD_MODE_DEFAULT, len); +} + +/** + * @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); - modules->update_time = (int)appconfig_get_number(cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_UPDATE_EVERY, 1); + modules->update_every = (int)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION, + EBPF_CFG_UPDATE_EVERY, modules->update_every); - modules->apps_charts = appconfig_get_boolean(cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_APPLICATION, - CONFIG_BOOLEAN_YES); + modules->apps_charts = appconfig_get_boolean(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_APPLICATION, + modules->apps_charts); - modules->pid_map_size = (uint32_t)appconfig_get_number(cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_PID_SIZE, + modules->pid_map_size = (uint32_t)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_PID_SIZE, modules->pid_map_size); } @@ -507,20 +588,249 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, struct config *cfg) * update the variables. * * @param em the module structure - * @param cfg the configuration structure - * @param cfg_file the filename to load */ -void ebpf_update_module(ebpf_module_t *em, struct config *cfg, char *cfg_file) +void ebpf_update_module(ebpf_module_t *em) { char filename[FILENAME_MAX+1]; - ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_user_config_dir, cfg_file); - if (!ebpf_load_config(cfg, filename)) { - ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_stock_config_dir, cfg_file); - if (!ebpf_load_config(cfg, filename)) { - error("Cannot load the ebpf configuration file %s", cfg_file); + ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_user_config_dir, em->config_file); + if (!ebpf_load_config(em->cfg, filename)) { + ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_stock_config_dir, em->config_file); + if (!ebpf_load_config(em->cfg, filename)) { + error("Cannot load the ebpf configuration file %s", em->config_file); return; } } - ebpf_update_module_using_config(em, cfg); + ebpf_update_module_using_config(em); +} + +//---------------------------------------------------------------------------------------------------------------------- + +/** + * Load Address + * + * Helper used to get address from /proc/kallsym + * + * @param fa address structure + * @param fd file descriptor loaded inside kernel. + */ +void ebpf_load_addresses(ebpf_addresses_t *fa, int fd) +{ + if (fa->addr) + return ; + + procfile *ff = procfile_open("/proc/kallsyms", " \t:", PROCFILE_FLAG_DEFAULT); + if (!ff) + return; + + ff = procfile_readall(ff); + if (!ff) + return; + + fa->hash = simple_hash(fa->function); + + size_t lines = procfile_lines(ff), l; + for(l = 0; l < lines ;l++) { + char *fcnt = procfile_lineword(ff, l, 2); + uint32_t hash = simple_hash(fcnt); + if (fa->hash == hash && !strcmp(fcnt, fa->function)) { + char addr[128]; + snprintf(addr, 127, "0x%s", procfile_lineword(ff, l, 0)); + fa->addr = (unsigned long) strtoul(addr, NULL, 16); + uint32_t key = 0; + bpf_map_update_elem(fd, &key, &fa->addr, BPF_ANY); + } + } + + procfile_close(ff); +} + +//---------------------------------------------------------------------------------------------------------------------- + +/** + * Fill Algorithms + * + * Set one unique dimension for all vector position. + * + * @param algorithms the output vector + * @param length number of elements of algorithms vector + * @param algorithm algorithm used on charts. +*/ +void ebpf_fill_algorithms(int *algorithms, size_t length, int algorithm) +{ + size_t i; + for (i = 0; i < length; i++) { + algorithms[i] = algorithm; + } +} + +/** + * Fill Histogram dimension + * + * Fill the histogram dimension with the specified ranges + */ +char **ebpf_fill_histogram_dimension(size_t maximum) +{ + char *dimensions[] = { "us", "ms", "s"}; + int previous_dim = 0, current_dim = 0; + uint32_t previous_level = 1000, current_level = 1000; + uint32_t previous_divisor = 1, current_divisor = 1; + uint32_t current = 1, previous = 0; + uint32_t selector; + char **out = callocz(maximum, sizeof(char *)); + char range[128]; + size_t end = maximum - 1; + for (selector = 0; selector < end; selector++) { + snprintf(range, 127, "%u%s->%u%s", previous/previous_divisor, dimensions[previous_dim], + current/current_divisor, dimensions[current_dim]); + out[selector] = strdupz(range); + previous = current; + current <<= 1; + + if (previous_dim != 2 && previous > previous_level) { + previous_dim++; + + previous_divisor *= 1000; + previous_level *= 1000; + } + + if (current_dim != 2 && current > current_level) { + current_dim++; + + current_divisor *= 1000; + current_level *= 1000; + } + } + snprintf(range, 127, "%u%s->+Inf", previous/previous_divisor, dimensions[previous_dim]); + out[selector] = strdupz(range); + + return out; +} + +/** + * Histogram dimension cleanup + * + * Cleanup dimensions allocated with function ebpf_fill_histogram_dimension + * + * @param ptr + * @param length + */ +void ebpf_histogram_dimension_cleanup(char **ptr, size_t length) +{ + size_t i; + for (i = 0; i < length; i++) { + freez(ptr[i]); + } + freez(ptr); +} + +//---------------------------------------------------------------------------------------------------------------------- + +/** + * Open tracepoint path + * + * @param filename pointer to store the path + * @param length file length + * @param subsys is the name of your subsystem. + * @param eventname is the name of the event to trace. + * @param flags flags used with syscall open + * + * @return it returns a positive value on success and a negative otherwise. + */ +static inline int ebpf_open_tracepoint_path(char *filename, size_t length, char *subsys, char *eventname, int flags) +{ + snprintfz(filename, length, "%s/events/%s/%s/enable", NETDATA_DEBUGFS, subsys, eventname); + return open(filename, flags, 0); +} + +/** + * Is tracepoint enabled + * + * Check whether the tracepoint is enabled. + * + * @param subsys is the name of your subsystem. + * @param eventname is the name of the event to trace. + * + * @return it returns 1 when it is enabled, 0 when it is disabled and -1 on error. + */ +int ebpf_is_tracepoint_enabled(char *subsys, char *eventname) +{ + char text[FILENAME_MAX + 1]; + int fd = ebpf_open_tracepoint_path(text, FILENAME_MAX, subsys, eventname, O_RDONLY); + if (fd < 0) { + return -1; + } + + ssize_t length = read(fd, text, 1); + if (length != 1) { + close(fd); + return -1; + } + close(fd); + + return (text[0] == '1') ? CONFIG_BOOLEAN_YES : CONFIG_BOOLEAN_NO; +} + +/** + * Change Tracing values + * + * Change value for specific tracepoint enabling or disabling it according value given. + * + * @param subsys is the name of your subsystem. + * @param eventname is the name of the event to trace. + * @param value a value to enable (1) or disable (0) a tracepoint. + * + * @return It returns 0 on success and -1 otherwise + */ +static int ebpf_change_tracing_values(char *subsys, char *eventname, char *value) +{ + if (strcmp("0", value) && strcmp("1", value)) { + error("Invalid value given to either enable or disable a tracepoint."); + return -1; + } + + char filename[1024]; + int fd = ebpf_open_tracepoint_path(filename, 1023, subsys, eventname, O_WRONLY); + if (fd < 0) { + return -1; + } + + ssize_t written = write(fd, value, strlen(value)); + if (written < 0) { + close(fd); + return -1; + } + + close(fd); + return 0; +} + +/** + * Enable tracing values + * + * Enable a tracepoint on a system + * + * @param subsys is the name of your subsystem. + * @param eventname is the name of the event to trace. + * + * @return It returns 0 on success and -1 otherwise + */ +int ebpf_enable_tracing_values(char *subsys, char *eventname) +{ + return ebpf_change_tracing_values(subsys, eventname, "1"); +} + +/** + * Disable tracing values + * + * Disable tracing points enabled by collector + * + * @param subsys is the name of your subsystem. + * @param eventname is the name of the event to trace. + * + * @return It returns 0 on success and -1 otherwise + */ +int ebpf_disable_tracing_values(char *subsys, char *eventname) +{ + return ebpf_change_tracing_values(subsys, eventname, "0"); } diff --git a/libnetdata/ebpf/ebpf.h b/libnetdata/ebpf/ebpf.h index bc55d9595..73128f529 100644 --- a/libnetdata/ebpf/ebpf.h +++ b/libnetdata/ebpf/ebpf.h @@ -5,6 +5,7 @@ #include <bpf/bpf.h> #include <bpf/libbpf.h> +#include <stdlib.h> // Necessary for stdtoul #define NETDATA_DEBUGFS "/sys/kernel/debug/tracing/" #define NETDATA_KALLSYMS "/proc/kallsyms" @@ -14,10 +15,12 @@ #define EBPF_CFG_LOAD_MODE "ebpf load mode" #define EBPF_CFG_LOAD_MODE_DEFAULT "entry" #define EBPF_CFG_LOAD_MODE_RETURN "return" +#define EBPF_MAX_MODE_LENGTH 6 #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" /** * The next magic number is got doing the following math: @@ -57,6 +60,13 @@ #define NETDATA_EBPF_KERNEL_5_10 330240 /** + * Kernel 5.0 + * + * 327680 = 5*65536 +256*0 + */ +#define NETDATA_EBPF_KERNEL_5_0 327680 + +/** * Kernel 4.17 * * 266496 = 4*65536 + 17*256 @@ -80,6 +90,16 @@ #define VERSION_STRING_LEN 256 #define EBPF_KERNEL_REJECT_LIST_FILE "ebpf_kernel_reject_list.txt" +#define ND_EBPF_DEFAULT_MIN_PID 1U +#define ND_EBPF_MAP_FD_NOT_INITIALIZED (int)-1 + +typedef struct ebpf_addresses { + char *function; + uint32_t hash; + // We use long as address, because it matches system length + unsigned long addr; +} ebpf_addresses_t; + extern char *ebpf_user_config_dir; extern char *ebpf_stock_config_dir; @@ -99,10 +119,26 @@ typedef enum { #define ND_EBPF_DEFAULT_PID_SIZE 32768U +enum netdata_ebpf_map_type { + NETDATA_EBPF_MAP_STATIC = 0, + NETDATA_EBPF_MAP_RESIZABLE = 1, + NETDATA_EBPF_MAP_CONTROLLER = 2, + NETDATA_EBPF_MAP_CONTROLLER_UPDATED = 4, + NETDATA_EBPF_MAP_PID = 8 +}; + +enum netdata_controller { + NETDATA_CONTROLLER_APPS_ENABLED, + + NETDATA_CONTROLLER_END +}; + typedef struct ebpf_local_maps { char *name; uint32_t internal_input; uint32_t user_input; + uint32_t type; + int map_fd; } ebpf_local_maps_t; typedef struct ebpf_specify_name { @@ -117,9 +153,10 @@ typedef struct ebpf_module { const char *config_name; int enabled; void *(*start_routine)(void *); - int update_time; + int update_every; int global_charts; int apps_charts; + int cgroup_charts; netdata_run_mode_t mode; uint32_t thread_id; int optional; @@ -127,23 +164,46 @@ typedef struct ebpf_module { ebpf_local_maps_t *maps; ebpf_specify_name_t *names; uint32_t pid_map_size; + struct config *cfg; + const char *config_file; } ebpf_module_t; -extern int get_kernel_version(char *out, int size); +extern int ebpf_get_kernel_version(); extern int get_redhat_release(); extern int has_condition_to_run(int version); extern char *ebpf_kernel_suffix(int version, int isrh); -extern int ebpf_update_kernel(ebpf_data_t *ef); +extern void ebpf_update_kernel(char *ks, size_t length, int isrh, int version); extern struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char *kernel_string, - struct bpf_object **obj, - int *map_fd); + struct bpf_object **obj); -extern void ebpf_mount_config_name(char *filename, size_t length, char *path, char *config); +extern void ebpf_mount_config_name(char *filename, size_t length, char *path, const char *config); extern int ebpf_load_config(struct config *config, char *filename); -extern void ebpf_update_module_using_config(ebpf_module_t *modules, struct config *cfg); -extern void ebpf_update_module(ebpf_module_t *em, struct config *cfg, char *cfg_file); +extern void ebpf_update_module(ebpf_module_t *em); extern void ebpf_update_names(ebpf_specify_name_t *opt, ebpf_module_t *em); +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); + +// Histogram +#define NETDATA_EBPF_HIST_MAX_BINS 24UL +#define NETDATA_DISK_MAX 256U +#define NETDATA_DISK_HISTOGRAM_LENGTH (NETDATA_DISK_MAX * NETDATA_EBPF_HIST_MAX_BINS) + +typedef struct netdata_ebpf_histogram { + char *name; + char *title; + int order; + uint64_t histogram[NETDATA_EBPF_HIST_MAX_BINS]; +} netdata_ebpf_histogram_t; + +extern void ebpf_histogram_dimension_cleanup(char **ptr, size_t length); + +// Tracepoint helpers +// For more information related to tracepoints read https://www.kernel.org/doc/html/latest/trace/tracepoints.html +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); #endif /* NETDATA_EBPF_H */ diff --git a/libnetdata/json/jsmn.c b/libnetdata/json/jsmn.c index 952535897..2f48bd65a 100644 --- a/libnetdata/json/jsmn.c +++ b/libnetdata/json/jsmn.c @@ -183,7 +183,7 @@ static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, * * Parse JSON string and fill tokens. * - * @param parser the auxiliar vector used to parser + * @param parser the auxiliary vector used to parser * @param js the string to parse * @param len the string length * @param tokens the place to map the tokens diff --git a/libnetdata/libnetdata.h b/libnetdata/libnetdata.h index 77a1bbe7f..b49ab21a0 100644 --- a/libnetdata/libnetdata.h +++ b/libnetdata/libnetdata.h @@ -53,6 +53,7 @@ extern "C" { #include <pthread.h> #include <errno.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> @@ -90,6 +91,12 @@ extern "C" { #include <uv.h> #include <assert.h> +// CentOS 7 has older version that doesn't define this +// same goes for MacOS +#ifndef UUID_STR_LEN +#define UUID_STR_LEN (37) +#endif + #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> #endif diff --git a/libnetdata/log/log.h b/libnetdata/log/log.h index 58cc0d26c..c8380d0c1 100644 --- a/libnetdata/log/log.h +++ b/libnetdata/log/log.h @@ -44,7 +44,7 @@ extern "C" { #define D_RRDENGINE 0x0000000100000000 #define D_ACLK 0x0000000200000000 #define D_METADATALOG 0x0000000400000000 -#define D_GUIDLOG 0x0000000800000000 +#define D_ACLK_SYNC 0x0000000800000000 #define D_SYSTEM 0x8000000000000000 //#define DEBUG (D_WEB_CLIENT_ACCESS|D_LISTENER|D_RRD_STATS) diff --git a/libnetdata/procfile/procfile.c b/libnetdata/procfile/procfile.c index 9867c19f6..ce412f4b0 100644 --- a/libnetdata/procfile/procfile.c +++ b/libnetdata/procfile/procfile.c @@ -69,7 +69,7 @@ static inline pfwords *pfwords_new(void) { } static inline void pfwords_reset(pfwords *fw) { - // debug(D_PROCFILE, PF_PREFIX ": reseting words"); + // debug(D_PROCFILE, PF_PREFIX ": resetting words"); fw->len = 0; } @@ -115,7 +115,7 @@ static inline pflines *pflines_new(void) { } static inline void pflines_reset(pflines *fl) { - // debug(D_PROCFILE, PF_PREFIX ": reseting lines"); + // debug(D_PROCFILE, PF_PREFIX ": resetting lines"); fl->len = 0; } diff --git a/libnetdata/socket/security.c b/libnetdata/socket/security.c index 63a71bcbd..6ac512de5 100644 --- a/libnetdata/socket/security.c +++ b/libnetdata/socket/security.c @@ -213,6 +213,7 @@ void security_start_ssl(int selector) { } netdata_srv_ctx = security_initialize_openssl_server(); + SSL_CTX_set_mode(netdata_srv_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); break; } case NETDATA_SSL_CONTEXT_STREAMING: { diff --git a/libnetdata/storage_number/storage_number.c b/libnetdata/storage_number/storage_number.c index 8ef1353b0..3e6a9f45c 100644 --- a/libnetdata/storage_number/storage_number.c +++ b/libnetdata/storage_number/storage_number.c @@ -2,17 +2,23 @@ #include "../libnetdata.h" +#define get_storage_number_flags(value) \ + ((((storage_number)(value)) & (1 << 24)) | \ + (((storage_number)(value)) & (1 << 25)) | \ + (((storage_number)(value)) & (1 << 26))) + storage_number pack_storage_number(calculated_number value, uint32_t flags) { // bit 32 = sign 0:positive, 1:negative // bit 31 = 0:divide, 1:multiply // bit 30, 29, 28 = (multiplier or divider) 0-7 (8 total) // bit 27 SN_EXISTS_100 // bit 26 SN_EXISTS_RESET - // bit 25 SN_EXISTS + // bit 25 SN_ANOMALY_BIT = 0: anomalous, 1: not anomalous // bit 24 to bit 1 = the value storage_number r = get_storage_number_flags(flags); - if(!value) return r; + if(!value) + goto RET_SN; int m = 0; calculated_number n = value, factor = 10; @@ -47,7 +53,7 @@ storage_number pack_storage_number(calculated_number value, uint32_t flags) { error("Number " CALCULATED_NUMBER_FORMAT " is too big.", value); #endif r += 0x00ffffff; - return r; + goto RET_SN; } } else { @@ -78,6 +84,10 @@ storage_number pack_storage_number(calculated_number value, uint32_t flags) { r += (storage_number)n; #endif +RET_SN: + if (r == SN_EMPTY_SLOT) + r = SN_ANOMALOUS_ZERO; + return r; } @@ -100,7 +110,7 @@ calculated_number unpack_storage_number(storage_number value) { factor = 100; // bit 26 SN_EXISTS_RESET - // bit 25 SN_EXISTS + // bit 25 SN_ANOMALY_BIT // bit 30, 29, 28 = (multiplier or divider) 0-7 (8 total) int mul = (value & ((1<<29)|(1<<28)|(1<<27))) >> 27; diff --git a/libnetdata/storage_number/storage_number.h b/libnetdata/storage_number/storage_number.h index 4ad7ff624..4101f69e0 100644 --- a/libnetdata/storage_number/storage_number.h +++ b/libnetdata/storage_number/storage_number.h @@ -60,17 +60,24 @@ typedef long double collected_number; typedef uint32_t storage_number; #define STORAGE_NUMBER_FORMAT "%u" -#define SN_EXISTS (1 << 24) // the value exists +#define SN_ANOMALY_BIT (1 << 24) // the anomaly bit of the value #define SN_EXISTS_RESET (1 << 25) // the value has been overflown #define SN_EXISTS_100 (1 << 26) // very large value (multiplier is 100 instead of 10) -// extract the flags -#define get_storage_number_flags(value) ((((storage_number)(value)) & (1 << 24)) | (((storage_number)(value)) & (1 << 25)) | (((storage_number)(value)) & (1 << 26))) +#define SN_DEFAULT_FLAGS SN_ANOMALY_BIT + #define SN_EMPTY_SLOT 0x00000000 +// When the calculated number is zero and the value is anomalous (ie. it's bit +// is zero) we want to return a storage_number representation that is +// different from the empty slot. We achieve this by mapping zero to +// SN_EXISTS_100. Unpacking the SN_EXISTS_100 value will return zero because +// its fraction field (as well as its exponent factor field) will be zero. +#define SN_ANOMALOUS_ZERO SN_EXISTS_100 + // checks -#define does_storage_number_exist(value) ((get_storage_number_flags(value) != 0)?1:0) -#define did_storage_number_reset(value) ((get_storage_number_flags(value) == SN_EXISTS_RESET)?1:0) +#define does_storage_number_exist(value) (((storage_number) (value)) != SN_EMPTY_SLOT) +#define did_storage_number_reset(value) ((((storage_number) (value)) & SN_EXISTS_RESET) != 0) storage_number pack_storage_number(calculated_number value, uint32_t flags); calculated_number unpack_storage_number(storage_number value); diff --git a/libnetdata/storage_number/tests/test_storage_number.c b/libnetdata/storage_number/tests/test_storage_number.c index 7ef18b1de..f90521cab 100644 --- a/libnetdata/storage_number/tests/test_storage_number.c +++ b/libnetdata/storage_number/tests/test_storage_number.c @@ -38,7 +38,7 @@ static void test_number_printing(void **state) print_calculated_number(value, -9999.9999999); assert_string_equal(value, "-9999.9999999"); - print_calculated_number(value, unpack_storage_number(pack_storage_number(16.777218L, SN_EXISTS))); + print_calculated_number(value, unpack_storage_number(pack_storage_number(16.777218L, SN_DEFAULT_FLAGS))); assert_string_equal(value, "16.77722"); } |