diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/ngx_bpf.c | 143 | ||||
-rw-r--r-- | src/core/ngx_bpf.h | 43 | ||||
-rw-r--r-- | src/core/ngx_core.h | 3 |
3 files changed, 189 insertions, 0 deletions
diff --git a/src/core/ngx_bpf.c b/src/core/ngx_bpf.c new file mode 100644 index 000000000..6b2611708 --- /dev/null +++ b/src/core/ngx_bpf.c @@ -0,0 +1,143 @@ + +/* + * Copyright (C) Nginx, Inc. + */ + + +#include <ngx_config.h> +#include <ngx_core.h> + +#define NGX_BPF_LOGBUF_SIZE (16 * 1024) + + +static ngx_inline int +ngx_bpf(enum bpf_cmd cmd, union bpf_attr *attr, unsigned int size) +{ + return syscall(__NR_bpf, cmd, attr, size); +} + + +void +ngx_bpf_program_link(ngx_bpf_program_t *program, const char *symbol, int fd) +{ + ngx_uint_t i; + ngx_bpf_reloc_t *rl; + + rl = program->relocs; + + for (i = 0; i < program->nrelocs; i++) { + if (ngx_strcmp(rl[i].name, symbol) == 0) { + program->ins[rl[i].offset].src_reg = 1; + program->ins[rl[i].offset].imm = fd; + } + } +} + + +int +ngx_bpf_load_program(ngx_log_t *log, ngx_bpf_program_t *program) +{ + int fd; + union bpf_attr attr; +#if (NGX_DEBUG) + char buf[NGX_BPF_LOGBUF_SIZE]; +#endif + + ngx_memzero(&attr, sizeof(union bpf_attr)); + + attr.license = (uint64_t) program->license; + attr.prog_type = program->type; + attr.insns = (uint64_t) program->ins; + attr.insn_cnt = program->nins; + +#if (NGX_DEBUG) + /* for verifier errors */ + attr.log_buf = (uint64_t) buf; + attr.log_size = NGX_BPF_LOGBUF_SIZE; + attr.log_level = 1; +#endif + + fd = ngx_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); + if (fd < 0) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "failed to load BPF program"); + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, + "bpf verifier: %s", buf); + + return -1; + } + + return fd; +} + + +int +ngx_bpf_map_create(ngx_log_t *log, enum bpf_map_type type, int key_size, + int value_size, int max_entries, uint32_t map_flags) +{ + int fd; + union bpf_attr attr; + + ngx_memzero(&attr, sizeof(union bpf_attr)); + + attr.map_type = type; + attr.key_size = key_size; + attr.value_size = value_size; + attr.max_entries = max_entries; + attr.map_flags = map_flags; + + fd = ngx_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); + if (fd < 0) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "failed to create BPF map"); + return NGX_ERROR; + } + + return fd; +} + + +int +ngx_bpf_map_update(int fd, const void *key, const void *value, uint64_t flags) +{ + union bpf_attr attr; + + ngx_memzero(&attr, sizeof(union bpf_attr)); + + attr.map_fd = fd; + attr.key = (uint64_t) key; + attr.value = (uint64_t) value; + attr.flags = flags; + + return ngx_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); +} + + +int +ngx_bpf_map_delete(int fd, const void *key) +{ + union bpf_attr attr; + + ngx_memzero(&attr, sizeof(union bpf_attr)); + + attr.map_fd = fd; + attr.key = (uint64_t) key; + + return ngx_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr)); +} + + +int +ngx_bpf_map_lookup(int fd, const void *key, void *value) +{ + union bpf_attr attr; + + ngx_memzero(&attr, sizeof(union bpf_attr)); + + attr.map_fd = fd; + attr.key = (uint64_t) key; + attr.value = (uint64_t) value; + + return ngx_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); +} diff --git a/src/core/ngx_bpf.h b/src/core/ngx_bpf.h new file mode 100644 index 000000000..f62a36e11 --- /dev/null +++ b/src/core/ngx_bpf.h @@ -0,0 +1,43 @@ + +/* + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_BPF_H_INCLUDED_ +#define _NGX_BPF_H_INCLUDED_ + + +#include <ngx_config.h> +#include <ngx_core.h> + +#include <linux/bpf.h> + + +typedef struct { + char *name; + int offset; +} ngx_bpf_reloc_t; + +typedef struct { + char *license; + enum bpf_prog_type type; + struct bpf_insn *ins; + size_t nins; + ngx_bpf_reloc_t *relocs; + size_t nrelocs; +} ngx_bpf_program_t; + + +void ngx_bpf_program_link(ngx_bpf_program_t *program, const char *symbol, + int fd); +int ngx_bpf_load_program(ngx_log_t *log, ngx_bpf_program_t *program); + +int ngx_bpf_map_create(ngx_log_t *log, enum bpf_map_type type, int key_size, + int value_size, int max_entries, uint32_t map_flags); +int ngx_bpf_map_update(int fd, const void *key, const void *value, + uint64_t flags); +int ngx_bpf_map_delete(int fd, const void *key); +int ngx_bpf_map_lookup(int fd, const void *key, void *value); + +#endif /* _NGX_BPF_H_INCLUDED_ */ diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h index 8e6c756c9..256836546 100644 --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -95,6 +95,9 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c); #include <ngx_connection.h> #include <ngx_syslog.h> #include <ngx_proxy_protocol.h> +#if (NGX_HAVE_BPF) +#include <ngx_bpf.h> +#endif #define LF (u_char) '\n' |