From c217b25390299cabbe72fb718c09ab56906515a0 Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Thu, 7 Feb 2019 23:37:04 -0800 Subject: [PATCH 1/2] add bcc_create_map_xattr() and refactor bcc_create_map() Added bcc_create_map_xattr() function which takes a libbpf bpf_create_map_attr pointer as the argument. This api will be later used to create maps with btf fd and key/value btf type ids. bcc_create_map() is refactored to use bcc_create_map_xattr(). Signed-off-by: Yonghong Song --- src/cc/libbpf.c | 36 ++++++++++++++++++++++++------------ src/cc/libbpf.h | 3 +++ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/cc/libbpf.c b/src/cc/libbpf.c index 0cf788dd7394..76afc02c6045 100644 --- a/src/cc/libbpf.c +++ b/src/cc/libbpf.c @@ -198,19 +198,17 @@ static uint64_t ptr_to_u64(void *ptr) return (uint64_t) (unsigned long) ptr; } -int bcc_create_map(enum bpf_map_type map_type, const char *name, - int key_size, int value_size, - int max_entries, int map_flags) +int bcc_create_map_xattr(struct bpf_create_map_attr *attr) { - size_t name_len = name ? strlen(name) : 0; - char map_name[BPF_OBJ_NAME_LEN]; + size_t name_len = attr->name ? strlen(attr->name) : 0; + char map_name[BPF_OBJ_NAME_LEN] = {}; - memcpy(map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1)); - int ret = bpf_create_map_name(map_type, map_name, key_size, value_size, - max_entries, map_flags); + memcpy(map_name, attr->name, min(name_len, BPF_OBJ_NAME_LEN - 1)); + attr->name = map_name; + int ret = bpf_create_map_xattr(attr); if (ret < 0 && name_len && (errno == E2BIG || errno == EINVAL)) { - ret = bpf_create_map(map_type, key_size, value_size, - max_entries, map_flags); + map_name[0] = '\0'; + ret = bpf_create_map_xattr(attr); } if (ret < 0 && errno == EPERM) { @@ -221,13 +219,27 @@ int bcc_create_map(enum bpf_map_type map_type, const char *name, rl.rlim_max = RLIM_INFINITY; rl.rlim_cur = rl.rlim_max; if (setrlimit(RLIMIT_MEMLOCK, &rl) == 0) - ret = bpf_create_map(map_type, key_size, value_size, - max_entries, map_flags); + ret = bpf_create_map_xattr(attr); } } return ret; } +int bcc_create_map(enum bpf_map_type map_type, const char *name, + int key_size, int value_size, + int max_entries, int map_flags) +{ + struct bpf_create_map_attr attr = {}; + + attr.map_type = map_type; + attr.name = name; + attr.key_size = key_size; + attr.value_size = value_size; + attr.max_entries = max_entries; + attr.map_flags = map_flags; + return bcc_create_map_xattr(&attr); +} + int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags) { return bpf_map_update_elem(fd, key, value, flags); diff --git a/src/cc/libbpf.h b/src/cc/libbpf.h index fdcd65caa063..d2c6fa6d4062 100644 --- a/src/cc/libbpf.h +++ b/src/cc/libbpf.h @@ -26,6 +26,8 @@ extern "C" { #endif +struct bpf_create_map_attr; + enum bpf_probe_attach_type { BPF_PROBE_ENTRY, BPF_PROBE_RETURN @@ -34,6 +36,7 @@ enum bpf_probe_attach_type { int bcc_create_map(enum bpf_map_type map_type, const char *name, int key_size, int value_size, int max_entries, int map_flags); +int bcc_create_map_xattr(struct bpf_create_map_attr *attr); int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags); int bpf_lookup_elem(int fd, void *key, void *value); int bpf_delete_elem(int fd, void *key); From 8c06807ea5746f8de0a8a1ce3b165b209115c50c Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Fri, 8 Feb 2019 00:12:17 -0800 Subject: [PATCH 2/2] add bcc_prog_load_xattr() and refactor bcc_prog_load() Added bcc_prog_load_xattr() function which takes a libbpf bpf_load_program_attr pointer (among others) as an argument. This api will be later used to load bpf programs with btf fd, func_info and line_info. bcc_prog_load() is refactored to use bcc_prog_load_xattr(). Signed-off-by: Yonghong Song --- src/cc/libbpf.c | 93 +++++++++++++++++++++++++------------------------ src/cc/libbpf.h | 6 +++- 2 files changed, 53 insertions(+), 46 deletions(-) diff --git a/src/cc/libbpf.c b/src/cc/libbpf.c index 76afc02c6045..0c9af6960d69 100644 --- a/src/cc/libbpf.c +++ b/src/cc/libbpf.c @@ -454,40 +454,31 @@ int bpf_prog_get_tag(int fd, unsigned long long *ptag) return 0; } -int bcc_prog_load(enum bpf_prog_type prog_type, const char *name, - const struct bpf_insn *insns, int prog_len, - const char *license, unsigned kern_version, - int log_level, char *log_buf, unsigned log_buf_size) +int bcc_prog_load_xattr(struct bpf_load_program_attr *attr, int prog_len, + char *log_buf, unsigned log_buf_size) { - size_t name_len = name ? strlen(name) : 0; - union bpf_attr attr; - char *tmp_log_buf = NULL; - unsigned tmp_log_buf_size = 0; + size_t name_len = attr->name ? strlen(attr->name) : 0; + char *tmp_log_buf = NULL, *attr_log_buf = NULL; + unsigned tmp_log_buf_size = 0, attr_log_buf_size = 0; int ret = 0, name_offset = 0; + char prog_name[BPF_OBJ_NAME_LEN] = {}; - memset(&attr, 0, sizeof(attr)); - - attr.prog_type = prog_type; - attr.kern_version = kern_version; - attr.license = ptr_to_u64((void *)license); - - attr.insns = ptr_to_u64((void *)insns); - attr.insn_cnt = prog_len / sizeof(struct bpf_insn); - if (attr.insn_cnt > BPF_MAXINSNS) { + unsigned insns_cnt = prog_len / sizeof(struct bpf_insn); + if (insns_cnt > BPF_MAXINSNS) { errno = EINVAL; fprintf(stderr, "bpf: %s. Program %s too large (%u insns), at most %d insns\n\n", - strerror(errno), name, attr.insn_cnt, BPF_MAXINSNS); + strerror(errno), attr->name, insns_cnt, BPF_MAXINSNS); return -1; } + attr->insns_cnt = insns_cnt; - attr.log_level = log_level; - if (attr.log_level > 0) { + if (attr->log_level > 0) { if (log_buf_size > 0) { // Use user-provided log buffer if availiable. log_buf[0] = 0; - attr.log_buf = ptr_to_u64(log_buf); - attr.log_size = log_buf_size; + attr_log_buf = log_buf; + attr_log_buf_size = log_buf_size; } else { // Create and use temporary log buffer if user didn't provide one. tmp_log_buf_size = LOG_BUF_SIZE; @@ -495,32 +486,33 @@ int bcc_prog_load(enum bpf_prog_type prog_type, const char *name, if (!tmp_log_buf) { fprintf(stderr, "bpf: Failed to allocate temporary log buffer: %s\n\n", strerror(errno)); - attr.log_level = 0; + attr->log_level = 0; } else { tmp_log_buf[0] = 0; - attr.log_buf = ptr_to_u64(tmp_log_buf); - attr.log_size = tmp_log_buf_size; + attr_log_buf = tmp_log_buf; + attr_log_buf_size = tmp_log_buf_size; } } } if (name_len) { - if (strncmp(name, "kprobe__", 8) == 0) + if (strncmp(attr->name, "kprobe__", 8) == 0) name_offset = 8; - else if (strncmp(name, "tracepoint__", 12) == 0) + else if (strncmp(attr->name, "tracepoint__", 12) == 0) name_offset = 12; - else if (strncmp(name, "raw_tracepoint__", 16) == 0) + else if (strncmp(attr->name, "raw_tracepoint__", 16) == 0) name_offset = 16; - memcpy(attr.prog_name, name + name_offset, + memcpy(prog_name, attr->name + name_offset, min(name_len - name_offset, BPF_OBJ_NAME_LEN - 1)); + attr->name = prog_name; } - ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); + ret = bpf_load_program_xattr(attr, attr_log_buf, attr_log_buf_size); // BPF object name is not supported on older Kernels. // If we failed due to this, clear the name and try again. if (ret < 0 && name_len && (errno == E2BIG || errno == EINVAL)) { - memset(attr.prog_name, 0, BPF_OBJ_NAME_LEN); - ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); + prog_name[0] = '\0'; + ret = bpf_load_program_xattr(attr, attr_log_buf, attr_log_buf_size); } if (ret < 0 && errno == EPERM) { @@ -536,7 +528,7 @@ int bcc_prog_load(enum bpf_prog_type prog_type, const char *name, rl.rlim_max = RLIM_INFINITY; rl.rlim_cur = rl.rlim_max; if (setrlimit(RLIMIT_MEMLOCK, &rl) == 0) - ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); + ret = bpf_load_program_xattr(attr, attr_log_buf, attr_log_buf_size); } } @@ -545,11 +537,9 @@ int bcc_prog_load(enum bpf_prog_type prog_type, const char *name, // User has provided a log buffer. if (log_buf_size) { // If logging is not already enabled, enable it and do the syscall again. - if (attr.log_level == 0) { - attr.log_level = 1; - attr.log_buf = ptr_to_u64(log_buf); - attr.log_size = log_buf_size; - ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); + if (attr->log_level == 0) { + attr->log_level = 1; + ret = bpf_load_program_xattr(attr, log_buf, log_buf_size); } // Print the log message and return. bpf_print_hints(ret, log_buf); @@ -563,8 +553,8 @@ int bcc_prog_load(enum bpf_prog_type prog_type, const char *name, if (tmp_log_buf) free(tmp_log_buf); tmp_log_buf_size = LOG_BUF_SIZE; - if (attr.log_level == 0) - attr.log_level = 1; + if (attr->log_level == 0) + attr->log_level = 1; for (;;) { tmp_log_buf = malloc(tmp_log_buf_size); if (!tmp_log_buf) { @@ -573,10 +563,7 @@ int bcc_prog_load(enum bpf_prog_type prog_type, const char *name, goto return_result; } tmp_log_buf[0] = 0; - attr.log_buf = ptr_to_u64(tmp_log_buf); - attr.log_size = tmp_log_buf_size; - - ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); + ret = bpf_load_program_xattr(attr, tmp_log_buf, tmp_log_buf_size); if (ret < 0 && errno == ENOSPC) { // Temporary buffer size is not enough. Double it and try again. free(tmp_log_buf); @@ -590,7 +577,7 @@ int bcc_prog_load(enum bpf_prog_type prog_type, const char *name, // Check if we should print the log message if log_level is not 0, // either specified by user or set due to error. - if (attr.log_level > 0) { + if (attr->log_level > 0) { // Don't print if user enabled logging and provided log buffer, // but there is no error. if (log_buf && ret < 0) @@ -605,6 +592,22 @@ int bcc_prog_load(enum bpf_prog_type prog_type, const char *name, return ret; } +int bcc_prog_load(enum bpf_prog_type prog_type, const char *name, + const struct bpf_insn *insns, int prog_len, + const char *license, unsigned kern_version, + int log_level, char *log_buf, unsigned log_buf_size) +{ + struct bpf_load_program_attr attr = {}; + + attr.prog_type = prog_type; + attr.name = name; + attr.insns = insns; + attr.license = license; + attr.kern_version = kern_version; + attr.log_level = log_level; + return bcc_prog_load_xattr(&attr, prog_len, log_buf, log_buf_size); +} + int bpf_open_raw_sock(const char *name) { struct sockaddr_ll sll; diff --git a/src/cc/libbpf.h b/src/cc/libbpf.h index d2c6fa6d4062..18dcc54823e2 100644 --- a/src/cc/libbpf.h +++ b/src/cc/libbpf.h @@ -27,6 +27,7 @@ extern "C" { #endif struct bpf_create_map_attr; +struct bpf_load_program_attr; enum bpf_probe_attach_type { BPF_PROBE_ENTRY, @@ -60,9 +61,12 @@ int bpf_get_next_key(int fd, void *key, void *next_key); * initial attemp was insufficient in size. */ int bcc_prog_load(enum bpf_prog_type prog_type, const char *name, - const struct bpf_insn *insns, int insn_len, + const struct bpf_insn *insns, int prog_len, const char *license, unsigned kern_version, int log_level, char *log_buf, unsigned log_buf_size); +int bcc_prog_load_xattr(struct bpf_load_program_attr *attr, + int prog_len, char *log_buf, + unsigned log_buf_size); int bpf_attach_socket(int sockfd, int progfd);